黑白棋课程设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
黑白棋课程设计
攀枝花学院课程设计
题目:黑白棋游戏
院(系):数学与计算机学院
年级专业: 2014级软件工程
姓名:田坤林
学号: 201410804095 指导教师:陈斌
二〇一五年一月十日
攀枝花学院教务处制
攀枝花学院本科学生课程设计任务书
课程设计(论文)指导教师成绩评定表
摘要
黑白棋,又叫反棋(Reversi)、奥赛罗棋(Othello)、苹果棋或翻转棋。
黑白棋在西方和日本很流行。
游戏通过相互翻转对方的棋子,最后以棋盘上谁的棋子多来判断胜负。
棋子:黑白棋棋子每颗由黑白两色组成,一面白,一面黑,共64个(包括棋盘中央的4个)。
棋子呈圆饼形。
棋盘:黑白棋棋盘由64格的正方格组成,游戏进行时棋子要下在格内。
棋盘可分为“角”、“边”以及黑白棋“中腹”。
现今的棋盘多以8x8较为普遍。
棋钟:正式的比赛中可以使用棋钟对选手的时间进行限制。
非正式的对局中一般不使用棋钟。
黑白棋的棋盘是一个有8*8方格的棋盘。
下棋时将棋下在空格中间,而不是像围棋一样下在交叉点上。
开始时在棋盘正中有两白两黑四个棋子交叉放置,黑棋总是先下子。
下子的方法把自己颜色的棋子放在棋盘的空格上,而当自己放下的棋子在横、竖、斜八个方向内有一个自己的棋子,则被夹在中间的全部翻转会成为自己的棋子。
并且,只有在可以翻转棋子的地方才可以下子。
如果玩家在棋盘上没有地方可以下子,则该玩家对手可以连下。
双方都没有棋子可以下时棋局结束,以棋子数目来计算胜负,棋子多的一方获胜。
在棋盘还没有下满时,如果一方的棋子已经被对方吃光,则棋局也结束。
将对手棋子吃光的一方获胜。
每个“翻转棋”游戏开始时,棋盘上已经交叉放好了四颗棋子。
其中两颗是黑棋,另两颗是白棋。
黑棋总是先走。
当您的棋子在某一直线方向包围了对手的棋子时,就可以翻转这些棋子的颜色,使它们成为您方的颜色。
例如,如果您执黑棋,并且看到在一排白棋的某一
端是一颗黑棋,那么当您将一颗黑棋放在这一排的另一端时,所有的白棋都将翻转并变为黑棋!所有的直线方向均有效:水平、垂直和斜线方向。
走棋的唯一规则是只能走包围并翻转对手的棋子。
每一回合都必须至少翻转一颗对手的棋子。
按规则不能再走棋时,这一回合弃权。
计算机会自动将控制权交给对方。
关键词黑白棋反棋(Reversi)奥赛罗棋(Othello)苹果棋翻转棋
目录
摘要 (I)
1 需求分析 (1)
1.1 需求概述 (1)
1.2 需求环境 (1)
1.3 功能描述 (1)
2 概要设计 (2)
2.1 程序设计思路 (2)
2.2 程序流程图 (2)
3 详细设计 (3)
3.1 程序源代码 (3)
3.1.1代码功能 (3)
3.1.2 所有源代码 (3)
4 测试与运行 (11)
结束语 (16)
1 需求分析
1.1 需求概述
(1)收集资料,全面分析课题,分解问题,形成中体编程思路;
(2)深入分析各个小问题,编写个部分程序模块;
(3)对于设计中用到的关键函数,要联系实际问题进行具体介绍;
(4)上机调试,确保程序能正确运行;
(5)设计完成后提交课程设计报告;
1.2 需求环境
本课程设计需要的设备为硬件要求和软件配置要求具体要求如下:
①硬件要求:一台计算机。
②软件配置:WINDOWS、C/VC++6.0。
1.3 功能描述
编写一个《黑白棋游戏》的C程序,包括以下功能:
初始状态:在一个8*8的棋盘中央交叉排放黑白棋子各两枚,白棋先走。
(1)每个棋手下棋时,摆子的位置必须是以自己的棋子能包围住对方一个或多个棋子,被包围住的对方棋子将成为自己的棋子。
包围的方向可以是上下左右以及斜线8个方向,只要能连成一线即可。
(2)当轮到某一个棋手下子,但是他没有可以包围对方棋子的位置时,他必须停步,让对方走棋,直到他可以走为止。
2 概要设计
2.1 程序设计思路
(1)首先设计程序进入界面。
(2)在说明玩家和电脑各自的棋子。
(3)详细说明黑白棋的规则。
并指引玩家开始游戏。
(4)初始棋盘。
(5)设计黑白棋程序的主体。
2.2 程序流程图
3 详细设计
3.1 程序源代码
代码功能
#include <stdio.h>
#include <ctype.h> //定义了一批C语言字符分类函数//
#define SIZE 8 //定义SIZE的值为8//
void display(char board[][SIZE]); //显示,输出函数//
int valid_moves(char board[][SIZE],int moves[][SIZE],char player); //该函数将前一数组各项复制到后一数组当中。
主要用于黑白棋的人工智能。
//
void make_move(char board[][SIZE],int row,int col,char player); //该函数用于玩家的下棋位置行列的输入//
void computer_move(char board[][SIZE],int moves[][SIZE],char player); int get_score(char board[][SIZE],char player); //计算比赛结果//
int best_move(char board[][SIZE],int moves[][SIZE],char player);
所有源代码
#include <stdio.h>
#include <ctype.h>
#define SIZE 8
void display(char board[][SIZE]);
int valid_moves(char board[][SIZE],int moves[][SIZE],char player);
void make_move(char board[][SIZE],int row,int col,char player);
void computer_move(char board[][SIZE],int moves[][SIZE],char player); int get_score(char board[][SIZE],char player);
int best_move(char board[][SIZE],int moves[][SIZE],char player);
int main()
{
char board[SIZE][SIZE]={0};
int moves[SIZE][SIZE]={0};
int row=0;
int col=0;
int no_of_games=0;
int no_of_moves=0;
int invalid_moves=0;
int comp_score=0;
int user_score=0;
char y=0;
char x=0;
char again=0;
int player=0;
printf("\n黑白棋--奥赛罗棋--made by 田坤林\n\n");
printf("欢迎来到黑白棋的世界!棋子有些奇怪哦,牢记住自己的棋子样子吧!\n"); printf(" 你的棋子是这样子的哦- (o)\n 电脑则是这这这样子的- (*).\n"); printf("想在哪个方格落棋的话,请先输入方格的行数,\n"
"然后再输入方格的列数哦!\n");
printf("\n祝你好运哦,按回车键就开始咯。
\n");
scanf("%c",&again);
do
{
player=++no_of_games%2;
no_of_moves=4;
for(row=0;row<SIZE;row++)
for(col=0;col<SIZE;col++)
board[row][col]=' ';
board[SIZE/2-1][SIZE/2-1]=board[SIZE/2][SIZE/2]='o';
board[SIZE/2-1][SIZE/2]=board[SIZE/2][SIZE/2-1]='*';
do
{
display(board);
if(player++%2)
{
if(valid_moves(board,moves,'o'))
{
for(;;)
{
fflush(stdin);
printf("Please enter your move (行列): ");
scanf("%d%c",&x,&y);
y=tolower(y)-'a';
x--;
if(x>=0&&y>=0&&x<SIZE&&y<SIZE&&moves[x][y])
{
make_move(board,x,y,'o');
no_of_moves++;
break;
}
else
printf("莫法这样子下的哦,换个地方试试。
\n");
}
}
else
if(++invalid_moves<2)
{
fflush(stdin);
printf("\n哦啊,我竟走投无路了,哎,你来吧!");
scanf("%c",&again);
}
else
printf("\n(*^__^*) ,我们都没法落子了,Game Over!看看谁的棋子多谁就赢啦......\n");
}
else
{
if(valid_moves(board,moves,'*'))
{
invalid_moves=0;
computer_move(board,moves,'*');
no_of_moves++;
}
else
{
if(++invalid_moves<2)
printf("\n哦啊,我竟走投无路了,哎,你来吧!\n");
else
printf("\n(*^__^*) ,我们都没法落子了,Game Over!看看谁的棋子多谁就赢啦......\n");
}
}
}while(no_of_moves<SIZE*SIZE&&invalid_moves<2);
display(board);
comp_score=user_score=0;
for(row=0;row<SIZE;row++)
for(col=0;col<SIZE;col++)
{
comp_score+=board[row][col]=='*';
user_score+=board[row][col]=='o';
}
printf("The final score is:\n");
printf("Computer %d\n User %d\n\n",comp_score,user_score);
fflush(stdin);
printf("你想再来一发么?(y/n): "); scanf("%c",&again);
}while(tolower(again)=='y');
printf("\n嘻嘻,下次再见咯!\n"); }
void display(char board[][SIZE]) {
int row=0;
int col=0;
char col_label='a';
printf("\n ");
for(col=0;col<SIZE;col++)
printf(" %c",col_label+col); printf("\n");
for(row=0;row<SIZE;row++)
{
printf(" +");
for(col=0;col<SIZE;col++)
printf("---+");
printf("\n%2d|",row+1);
for(col=0;col<SIZE;col++)
printf(" %c |",board[row][col]);
printf("\n");
}
printf(" +");
for(col=0;col<SIZE;col++)
printf("---+");
printf("\n");
}
int valid_moves(char board[][SIZE],int moves[][SIZE],char player) {
int rowdelta=0;
int coldelta=0;
int row=0;
int col=0;
int x=0;
int y=0;
int no_of_moves=0;
char opponent=(player=='o')?'*':'o';
for(row=0;row<SIZE;row++)
for(col=0;col<SIZE;col++)
moves[row][col]=0;
for(row=0;row<SIZE;row++)
for(col=0;col<SIZE;col++)
{
if(board[row][col]!=' ')
continue;
for(rowdelta=-1;rowdelta<=1;rowdelta++)
for(coldelta=-1;coldelta<=1;coldelta++)
{
if(row+rowdelta<0||row+rowdelta>=SIZE|| col+coldelta<0||col+coldelta>=SIZE||
(rowdelta==0&&coldelta==0))
continue;
if(board[row+rowdelta][col+coldelta]==opponent) {
x=row+rowdelta;
y=col+coldelta;
for(;;)
{
x+=rowdelta;
y+=coldelta;
if(x<0||x>=SIZE||y<0||y>=SIZE)
break;
if(board[x][y]==' ')
break;
if(board[x][y]==player)
{
moves[row][col]=1;
no_of_moves++;
break;
}
}
}
}
}
return no_of_moves;
}
void make_move(char board[][SIZE],int row,int col,char player) {
int rowdelta=0;
int coldelta=0;
int x=0;
int y=0;
char opponent=(player=='o')?'*':'o';
board[row][col]=player;
for(rowdelta=-1;rowdelta<=1;rowdelta++)
for(coldelta=-1;coldelta<=1;coldelta++)
{
if(row+rowdelta<0||row+rowdelta>=SIZE||
col+coldelta<0||col+coldelta>=SIZE||
(rowdelta==0&&coldelta==0))
continue;
if(board[row+rowdelta][col+coldelta]==opponent)
{
x=row+rowdelta;
y=col+coldelta;
for(;;)
{
x+=rowdelta;
y+=coldelta;
if(x<0||x>=SIZE||y<0||y>=SIZE)
break;
if(board[x][y]==' ')
break;
if(board[x][y]==player)
{
while(board[x-=rowdelta][y-=coldelta]==opponent)
board[x][y]=player;
break;
}
}
}
}
}
int get_score(char board[][SIZE],char player)
{
int score=0;
int row=0;
int col=0;
char opponent=player=='o'?'*':'o';
for(row=0;row<SIZE;row++)
for(col=0;col<SIZE;col++)
{
score-=board[row][col]==opponent;
score+=board[row][col]==player;
}
return score;
}
int best_move(char board[][SIZE],int moves[][SIZE],char player) {
int row=0;
int col=0;
int i=0;
int j=0;
char opponent=player=='o'?'*':'o';
char new_board[SIZE][SIZE]={0};
int score=0;
int new_score=0;
for(row=0;row<SIZE;row++)
for(col=0;col<SIZE;col++)
{
if(!moves[row][col])
continue;
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
new_board[i][j]=board[i][j];
make_move(new_board,row,col,player);
new_score=get_score(new_board,player);
if(score<new_score)
score=new_score;
}
return score;
}
void computer_move(char board[][SIZE],int moves[][SIZE],char player) {
int row=0;
int col=0;
int best_row=0;
int best_col=0;
int i=0;
int j=0;
int new_score=0;
int score=100;
char temp_board[SIZE][SIZE];
int temp_moves[SIZE][SIZE];
char opponent=player=='o'?'*':'o';
for(row=0;row<SIZE;row++)
for(col=0;col<SIZE;col++)
{
if(moves[row][col]==0)
continue;
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
temp_board[i][j]=board[i][j];
make_move(temp_board,row,col,player);
valid_moves(temp_board,temp_moves,opponent);
new_score=best_move(temp_board,temp_moves,opponent);
if(new_score<score)
{
score=new_score;
best_row=row;
best_col=col;
}
}
make_move(board,best_row,best_col,player);
}
结束语
通过本次黑白棋程序设计,我觉得对自己有很大的提高,程序员的工作可以说很不简单,忙起来还真的有得让你忙个不完的。
得益的是这让我克服了平时爱偷懒的毛病,这在我以后的学习和工作中的心理定位和调节有很大的帮助。
从敲代码到运行成功,我感受到编程是一项非常繁琐周密的活动,它不仅需要一个人周密思考问题的能力,处理问题的能力,而且还需要有足够的耐心和严谨的作风,不得有半点马虎。
代码里,一丁点小错误就会致使整个程序没有办法运行而让我头疼。
但经过不懈努力,检查出错误,然后到运行成功,那种喜悦,是别人无法体会的快乐。
这个黑白棋游戏源程序的最大特点是采用了在主函数中调用子函数的思想,每一种功能都是用子函数的办法来进行处理,简洁、清晰、方便,不容易出现错误。
在输入错误时,本来想用一种警告的铃声来提醒用户,但由于所学的知识不多,自己的编程经验不足,按现有的知识水平,有些东西暂时还无法解决,还有待于在以后的学习中不断提高和改进!
本次程序设计让我初步学会了设计的方法,学会了怎样去借鉴别人的方法和经验,知道如何去查找资料和整合处理这些资料,提高了自己这方面的能力。
为以后大学的毕业论文打下了一个初步的基础,使我感到收益最大的是享受了一种成功的喜悦。
在这5天中,从开始的确定题目,到开始编写程序,我始终以严格要求自己,以积极的、正确的态度去完成每步的编程。
尽最大的努力去做好自己的工作,这个过程中,我都上网和到图书馆查找资料、敲代码、测试,取得很好的成果。
在这个艰难痛苦的环节里,常常会因为一小点错误而在编译失败与再
次修改的漫漫循环路中来回走。
但我相信,失败得越多,对人的考验就越多,在编译运行成功之后的享受成功的喜悦也就越多,另外在调试程序的过程中,不断的思考和运用已经学到的知识,这对于自己也是有很大的提高的。
经过这一段时间的学习,我学到了很多人生的哲理,懂得怎么样去定制计划,怎么样去实现这个计划,让我在编写工作过程中克服心理上的不良情绪,黑夜过去了,我收获的是黎明。
想想刚开始的时候,我都没接触过软件工程,缺乏经验,完成开题报告花费了我好多的时间,而且其中的纰漏也比较多,但是我并没有因为那样而放弃。
曾经在查找资料上很费神,想放弃的我,但想起这是我第一个程序,我便坚持了下来。
虽然我完成了任务,但在与同学进行交流时我发现我整合资料的能力还是具有很大的局限性,和老师进行交流,然后发现我整合的资料原来可以不那么繁琐详细就能让人看懂释。
在今后,我会更加努力去克服自己的不足,刻苦学习、勤奋工作,团结同学,提高自身综合素质。