黑白棋C语言课程设计

绝世美人儿
876次浏览
2021年01月18日 14:45
最佳经验
本文由作者推荐

伏低做小-雪字

2021年1月18日发(作者:戎之勤)

摘要

黑白棋
(REVERSI

OTHELL O)
,也叫苹果棋,翻转棋,是一个经典的策略性游戏。它使

8*8
的棋盘
,
由两人执黑子和白子轮流下棋,最后子多方为胜方。轮到一方下棋时,必
须把棋下在 与对方棋子相邻的空位上,要求所下的棋子和原有的已方棋子夹住对方的至少
一个棋子
(
横竖斜夹均可
)
,然后把被夹住的子变成己方的颜色
(
也叫吃子
)
。下棋过程中,
任何棋子既不会从棋盘上拿走,也不会从一个格子移到另一个格子。


黑白棋规则简单,
但是变化复杂,
是典型的易学难精
(A
MINUTE
TO
LEARN,
A
LIFETIME
TO MASTER),
它看似简单
,
实际奥妙无穷。


一般说来,下棋过程中,你必须尽量削减对手的行动力,同时增加自己的行动力,
这种策略我们 称之为行动力原则
(
或行动力战术
)
。当一方达到或接近这个目标时,我们就
称该棋手控制了棋局。另外,这个战术的目的是迫使对方下坏棋,如果对方虽然可选位置
很少, 但每一步却总有好棋,那战术目的就没有达成。记住,你必须让对方完全无好棋可
下。
黑白棋规则规定只能在对方棋子相邻的空位下棋,这就可以推出另一个原则。对方棋
子边上的空位越 多,你下棋的选择也就越多,换句话说,你的行动力就越强;相反,如果
你棋子边上的空位越少,对方可 下的位置也就越少。我们把相邻位置上有空位的子称为外
子,反之称为内子,连在一起的外子称为前线或 墙。下棋时要尽量减少自己的外子。


关键字:
黑白棋,
C
语言,数组,函数











1


黑白棋游戏

一、课程设计目的

1.
巩固和加深学生对
C
语言课程的基本知识的理解和掌握


2.
掌握
C
语言编程和程序调试的基本技能


3.
利用
C
语言进行基本的软件设计

4.
提高运用
C
语言解决实际问题的能力

5.
掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能。

二、实验器材及实验环境

硬件环境:装有
Windows 2000
或以上系统的微机系统

软件环境:
Turbo C 2.0
软件

三、黑白棋的总体设想

1.
设计思路

从已知的黑白棋游戏中可知,应该用二维数组表示程序的数据 ,数组两个下标可以表示棋
盘上的位置,
数组元素的值代表棋格中的状态,
共有三种情 况,
分别是空格、
黑棋和白棋,
这样给数组元素的取值设定为
0
、< br>1

2
。其中
0
代表空格,
1
代表白色棋 子,
2
代表黑色
棋子。这样程序的主要工作是接收棋手按键操作,一旦接收到回车键, 说明棋手摆子,先
判定是不是有效位置,也就是能不能包围住对方棋子,如果能,便对棋子所在的位置往 上
下、左右、左上、左下、右上、右下
8
个方向寻找被包围住的所有棋子(必须是连续 的,
中间不能有空格)
,将这些被包围住的对方棋子都变成自己的棋子,然后对当前棋盘中的< br>黑白棋个数进行统计并输出结果。如果没有这样的位置可以落子,则停步,让对方走棋,
重复上述 步骤,直到游戏结束。如果想提前终止游戏可以按
Esc




2.
结构设计

棋盘状态用数组
a[8][8]
初值为0
表示空格。函数的实体比较简单,因为要输出图形,所
以应初始化图形系统,图形工作方 式正确确定后,画出棋盘,调用
playtoplay()
人人对弈
函数开始游戏。一 旦游戏结束后,关闭图形系统,程序结束。

本次设计主要要设计函数有:

()
主函数

按照语法规则,首先定义使用到的常数、全局变量、函数原型说明。棋盘状态用数组
2


a[8][8]
,初值为
0
,表示空格。函数的实体比 较简单,因为要输出图形,所以应初始化图
形系统,
图形工作方式正确确定后,
画出棋 盘,
调用
playtoplay()
人人对弈函数开始游戏,
一旦游戏结束后 ,关闭图形系统,程序结束。

()
画棋盘函数

背景颜色设为蓝 色
,
从坐标
(100,100)
开始每隔
40
个单位用白色 画一条水平直线
,
一条
垂直线
,
构成棋盘
,
用循环 语句实现
.
画线函数
line()
的参数为线的起点和终点坐标
,< br>注意
要计算正确
.
函数
setfillstyle()
可以 设置填充模式和填充颜色
,fillellipse(int x,int
y,xradius,int
yradius)

x

y
为圆心
,xradius

yradius
为水平和垂直轴画一填充 椭

,

xradius

yradius
相等时
,
则画出的是圆
,
用它表示棋子。

yColor()
设置棋子的颜色

因为是两个棋手
,
同时 棋盘也在不断变化
,
所以要判断棋手和棋盘变化设置了这个函


函 数的参数为整型变量
t,
根据
t
的值来设计填充棋子的当前颜色
,< br>值为
1
代表白棋
,


2
代表黑棋。

lor()
恢复原来格子的状态

由于棋手在走棋的时候,他的棋子总是首先出现在棋盘的左上角

棋手要通过移动光< br>标键走到要落子的位置,
在经过的路程上显示当前棋子,
就会覆盖原来的棋盘状态。所以,
一旦棋子走过后,就应恢复原来的状态,是空格的依然显示空格,是棋子的就显示原来棋子的颜色,因为棋子移动过程并没有改变数组元素的值,所以可以根据数组元素的值判定
原来的状态 ,如果值是
1
,就恢复白色棋子,值是
2
则恢复黑色棋子,否则恢复蓝色空格 。

play()
人人对战函数

这是游戏进行的函数,主要是接收棋手的按键消息,其处理过程如下:


1
)按
Esc
键程序可以随时结束。


2
)按上下左右光标键,则改变棋子移动的坐标值。


3
)按回车键后判断:

1
)如落子的位置已经有棋则无效,继续压键。

2
)如落子位置是空格,可以将棋子落入格内,调用函数
QpChange()判断是否引起
棋盘的变化,函数值为
1
有变化,为
0
没变化。如 果棋盘有变化,说明将包围的对方棋子
吃掉,统计当前分数,如果棋盘没有变化,则说明落子的位置无法 包围对方的棋子也视为
无效棋。可以继续寻找合适的位置,但开始统计其落子次数,一旦尝试次数超过当 前棋盘
的空格数,则说明他无棋可走,则放弃此步,让对方下棋。

3
)如果 棋子变化后,格子已占满
64
格或一方棋子为
0
,则游戏结束,显示胜利方< br>信息。按任意键程序结束。


4
)重复上述步骤,直到游戏结束。

ge()
判断棋盘变化

当棋手按回车键落子后,就要分别往
8个方向判断是否包围住对方棋子,如果是,则
改变棋盘,也就是棋盘上黑白棋子的个数要发生变化。 表示黑白棋的图形用屏幕上的像素
3


坐标,而棋子的状态是数组元素< br>a
,所以要根据落子的坐标
x

y
计算出对应数组元素
a
的下标
i

j

i
代表行,
j< br>代表列,对于
8*8
的棋盘,它们的值为
0-7
,如果
j<6
,往右
边判断,从当前位置开始,用循环语句判断右边是否有一个或连续多个对方的棋子,遇到
自己的棋子或空格则结束循环,如果循环结束不是遇到空白,且列坐标小于
8
,则说明 这
些位置的棋子是被自己包围的对方棋子,将它们吃掉

也就是改变为自己的棋子,如 果有
棋子发生了变化,给棋盘变化标志值
yes
赋值为
1
,同样的方 法向左、上、下等
8
个方向
进行判断,并作相应的变化。如果所有方向都判断过,并 且没有引起棋盘的变化,则棋盘
变化标志值
yes

0
返回
yes
结束本函数。

e()
处理分数

根据当前数组元素的值判断分数,也就是各方棋子的个数, 如果数组元素值为
1
,白
棋棋子数累加,如果数组元素值为
2
,则黑 棋棋子数累加。

core()
输出成绩

利用设置实体填充模式填充矩形条清除掉前次的成绩,再利用
sprintf()
函 数将整数
转换为字符串的形式,再利用
outtextxy()
函数将成绩输出。
n()
输出胜利者结果

根据分数值
score1

score2
的大小得出下棋的结果,输出赢者信息。

3.
流程图

3.1playtoplay
函数流程图:

开始

换棋手

按键方向键

改变棋子坐标

统计分数

Y
按回车键

N
Y
当前位置有棋子?

N
调用
QpChang
e
棋盘有变化?


1
4


3.2
主函数流程图:

开始

初始化棋盘为
320*320

64
方格

调用
SetPlayColor

将棋子设为黑白两色

调用
playtoplay

棋手走棋

Y
结束

格子已满或一方没子了或有
Esc
输入?

N
调用
MoveColor
恢复格子

N
符合下子条件
?
换棋手

Y
回车键落子

调用
QpChange
改变棋盘


2
5


四、
C
语言实现

本设计是基于
Turbo C
强大的图形函数而成的,
Turbo C
提供了
70
多个图形函数,这些函
数包括在图形库文件

中,他们被 定义在
graphics.h
中。

源程序如下:

#include
图形系统头文件
*/
#include
#define
#define
#define
#define
BLUE 0xA80000
RED 0x0000A8
SOLID_FILL 2
DETECT
#define LEFT 0x4b00 /*
光标左键值
*/
#define RIGHT 0x4d00 /*
光标右键值
*/
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
#define ENTER 0x1c0d
int a[8][8]={0},key,s coreblack[2]={0},scorewhite[2]={0};
void qipan()/*
开始画面
*/
{ int i;
setbkcolor(BLUE);
for(i=100;i<=420;i+=40)
{
line(100,i,420,i);
line(i,100,i,420);
}
setcolor(0);/*
取消圆周围的一圈东西
*/
setfillstyle(SOLID_FILL,15);
fillellipse(500,200,15,15);
setfillstyle(SOLID_FILL,8);
fillellipse(500,300,15,15);
}
void playcolor(int t)/*
设置棋子第一次的颜色
*/
{
if(t%2==0)
6


setfillstyle(SOLID_FILL,15);
else
setfillstyle(SOLID_FILL,8);
}
void playcolortwo(int xx,int yy)/*
走了一步后恢复原来那里的格子
*/
{
if(yy<100)
setfillstyle(SOLID_FILL,BLUE);
else
switch(a[(xx-120)/40][(yy-120)/40])
{
case 1:
setfillstyle(SOLID_FILL,15);break;
case 2:
setfillstyle(SOLID_FILL,8);break;
default:
setfillstyle(SOLID_FILL,BLUE);
}
}
void qipanchange(int xxx,int yyx,int t)/*
棋盘的变化
,
也就是黑白的变化
*/
{
int i,j,k,kk,ii,jj;
i=(xxx-120)/40;
j=(yyx-120)/40;
playcolor(t);
if(j<6)/*
开始判断变化
*/ /*
往右边
*/
{
for(k=j+1;k<8;k++)
if(a[i][k]==a[i][j]||!a[i][k])
break;
if(a[i][k]&&k<8)
for(kk=j+1;kk {
a[i][kk]=a[i][j];
fillellipse(120+i*40,120+kk*40,15,15);
}
7

伏低做小-雪字


伏低做小-雪字


伏低做小-雪字


伏低做小-雪字


伏低做小-雪字


伏低做小-雪字


伏低做小-雪字


伏低做小-雪字