第6讲 棋类游戏井字棋游戏人机对弈
基于极大极小分析法的井字棋对弈

基于极大极小分析法的井字棋对弈任务分析:首先,我们要知道,“井字棋”游戏(又叫“三子棋”),是一款十分经典的益智小游戏,想必很多玩家都有玩过。
“井字棋”的棋盘很简单,是一个3×3的格子,很像中国文字中的“井”字,所以得名“井字棋”。
“井字棋”游戏的规则与“五子棋”十分类似,“五子棋”的规则是一方首先五子连成一线就胜利;“井字棋”是一方首先三子连成一线就胜利。
游戏时一方是电脑,另一方是玩家。
所以,这类游戏在开始时有两种方式:一种是玩家先走;另一种是电脑先走。
这是我们要考虑的第一个问题。
其次,由于与玩家对战的是计算机,所以我们要编写一个过程,它可以使程序模拟人的思维与人下棋(其实就是“人工智能”的体现),这个过程也是本游戏的关键。
此外,我们还要编写两个过程,其一用来时刻判断棋盘中是否有三个棋子连成一线;其二用来判断如果有三个棋子连成一线,是哪一方连成一线的,即判断哪一方获胜。
如图所示为井字棋的一个格局,而格局之间的关系是由比赛规则决定的.通常,这个关系不是线性的,因为从一个棋盘格局可以派生出几个格局.例如图左侧所示的格局可以派生出5歌格局.例如图右侧所示,而从每一个新的格局又可派生出4个可能出现的格局.因此,若将从对弈开始到结束的过程中所有可能出现的格局都画在一张图上,则可以得到一颗倒长的”树”.图1 对弈问题中格局之间的关系设计思路设有九个空格,由MAX,MIN二人对弈,轮到谁走棋谁就往空格上放一只自己的棋子,谁先使自己的棋子构成“三子成一线”(同一行或列或对角线全是某人的棋子),谁就取得了胜利。
用叉号表示MAX,用圆圈代表MIN。
为了不致于生成太大的博弈树,假设每次仅扩展两层。
估价函数定义如下:设棋局—为P,估价函数为e(P)。
(1) 若P对任何一方来说都不是获胜的位置,则e(P)=e(那些仍为MAX空着的完全的行、列或对角线的总数)-e(那些仍为MIN空着的完全的行、列或对角线的总数。
人工智能 井字棋

人工智能井字棋学院:信息工程学院教师:罗会兰专业:计算机软件和理论学号:6120160090姓名:朱玲简述5月23日,当今世界围棋第一人柯洁与计算机围棋程序“阿尔法狗”(Alpha Go)的第一场比赛结束,“阿尔法狗”以四分之一子优势赢得首场胜利。
这场比赛双方耗时4小时17分37秒,其中柯洁用时2小时46分43秒,“阿尔法狗”用时1小时30分54秒。
除了围观和好奇,人类骨子里的不服输以及想要看看人工智能到底有多厉害的求胜欲促成了这一挑战。
面对人类棋手注定完败于人工智能的结局,人类要做好的准备是全面迎接而非拒绝人工智能,努力去掌控而非臣服于人工智能。
接纳人工智能是今天社会发展、经济增长、人类演化的必然,更是人们生活的需求。
其实,很多人每天离不开的智能手机就是低端人工智能的应用。
更应当看到的现实是,人工智能的发展极具竞争性,未来谁在人工智能的研发和应用中落后,谁就会被淘汰。
而井字棋游戏的诞生更是吸引着不同年龄段的人群,无论男女老少都可以玩,也都喜欢玩,而当前微型计算机已经是在广大人群中流行者,用电脑来下井字棋更是一种时尚。
现在网络上出现了各种各样的井字棋软件,有大师级的,新手级的等等。
这些都满足了不同人群的需要,所以当前井字棋越来越被许多人所熟悉。
目前的井字棋程序的发展也非常快,从最初的双人发展到人机,然后到现在的网络对战,已经受到越来越多人的喜爱和重视。
井字棋不但容易上手,而且它区别于别的游戏,它不但能使人娱乐,而且能使人的头脑变的更加聪明。
而井字棋有两种对战模式,一是人机对战,二十人人对战。
这些给人无限乐趣的用途正式人工智能的杰作。
正因为这样它鼓励着人们对它不断的研究,这在很大程度上促进了人工智能的发展,反过来人工智能的理论和技术上的突破能够使井字棋程序更加完美,更受欢迎。
这是一个具有简单功能的井字棋游戏。
本设计的主要完成的是井字棋的人机对弈问题,即计算机与人交替落子,当行、列或对角有连续三个以上(包括三个)相同一方棋时,则判定一方胜利,如果所有位置都已经下满,且没有哪一方赢棋,则为和局。
C语言实现井字棋游戏(人机对弈)

C语⾔实现井字棋游戏(⼈机对弈)井字棋游戏:即三⼦棋,英⽂名叫Tic-Tac-Tic,是⼀种在3*3格⼦上进⾏的连珠游戏,和五⼦棋⽐较类似,由于棋盘⼀般不画边线框,格线排成井字故得名。
题⽬分析:要完成该游戏的编写,我们需要先分析出完成整个游戏过程都需要⼲什么?1.⾸先,需要定义出⼀个3*3的棋盘,根据相关知识,我们可以以⼆维数组的⽅式将棋盘表⽰出来;2.棋盘定义出来后,需要将棋盘初始化,将3*3⼆维数组的每⼀个位置初始化为‘ ’(空格);3.有了棋盘,我们就可以开始进⾏下棋了,⾸先要确定是玩家先下还是电脑先下。
在这⾥我们规定玩家先下且玩家的下棋⽅式为‘x’,电脑下棋⽅式为‘o’;4.每⼀次下完棋后需要进⾏检测,判断该下棋位置是否合法、判断是否胜利等等。
根据上述分析,可以⼤致定义出以下函数窗⼝:void InitGame();//初始化游戏(棋盘)void PrintChess();//输出棋盘void PlayerMove();//玩家下棋void ComputerMove();//电脑下棋char CheckGameOver();//判断游戏是否结束(玩家胜/电脑胜/和棋)初始化棋盘:将3*3的⼆维数组棋盘的每个位置初始化为‘ ’void InitGame(){for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++)chess_board[i][j] = ' ';}}输出棋盘:输出棋盘时,棋盘的风格可以根据⾃⼰的喜好来设计void PrintfChess()//输出棋盘,棋盘的设计可以根据⾃⼰的喜好设计{for (int i = 0; i < ROW; i++){printf("| %c | %c | %c |\n", chess_board[i][0], chess_board[i][1], chess_board[i][2]);if (i < ROW - 1)printf("|---|---|---|\n");}}玩家下棋:玩家输⼊下棋位置后,需要判断该位置是否合法、输⼊位置是否已被占⽤void PlayerMove()//玩家下棋{printf("玩家落⼦.\n");int row, col;while (1){printf("请输⼊⼀组坐标(下棋位置):>");scanf("%d %d", &row, &col);//检查坐标的有效性if (row < 0 || row > ROW || col < 0 || col > COL){printf("输⼊⾮法,请重新输⼊...");continue;}if (chess_board[row][col] != ' '){printf("输⼊的位置已被占⽤,请重新输⼊...");continue;}chess_board[row][col] = 'x';//x代表玩家下的棋break;}}电脑下棋:电脑下棋时,下棋的位置利⽤srand函数随机产⽣void ComputerMove()//电脑下棋{srand(time(0));while (1){int row = rand() % ROW;int col = rand() % COL;if (chess_board[row][col] != ' '){continue;}chess_board[row][col] = 'o';//o代表电脑下的棋break;}}检查棋盘:在检测棋盘时,分别判断⾏、列、对⾓线,在这⾥我规定:'x'代表玩家赢 'o'代表电脑赢 'h'代表和棋 'c'代表继续char CheckGameOver()//检测游戏是否结束{//检查⾏for (int i = 0; i < ROW; i++){if (chess_board[i][0] != ' '&& chess_board[i][0] == chess_board[i][1]&& chess_board[i][0] == chess_board[i][2])return chess_board[i][0];}//检查列for (int j = 0; j < COL; j++){if (chess_board[0][j] != ' '&& chess_board[0][j] == chess_board[1][j]&& chess_board[0][j] == chess_board[2][j])return chess_board[0][j];}//检查对⾓线if (chess_board[0][0] != ' '&& chess_board[0][0] == chess_board[1][1]&& chess_board[0][0] == chess_board[2][2])return chess_board[0][0];if (chess_board[0][2] != ' '&& chess_board[0][2] == chess_board[1][1]&& chess_board[0][2] == chess_board[2][0])return chess_board[0][2];//判断是否和棋if (ChessFull())return 'h';return 'c';}⾄此,主要的功能函数均已编写完毕,整个程序的流程如下所⽰:1.初始化棋盘;2.输出棋盘;3.玩家下棋;4.检测棋盘;5.电脑下棋;6.检测棋盘#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <time.h>#include <stdbool.h>#include <stdlib.h>#define START 1#define QUIT 0#define ROW 3#define COL 3static char chess_board[ROW][COL];//定义棋盘void StartGame();void InitGame();void PrintfChess();void PlayerMove();void ComputerMove();char CheckGameOver();bool ChessFull();int main(int argc, char* argv[]){int select = 1;while (select){printf("*********************\n");printf("* [1] Start Game *\n");printf("* [2] Over Game *\n");printf("*********************\n");printf("请选择:>");scanf_s("%d", &select);if (select == QUIT)break;if (select != START){printf("输⼊有错,请重新输⼊.....\n"); continue;}StartGame();}printf("GoodBye.....");return 0;}void StartGame(){char winner;//1 初始化游戏(棋盘)InitGame();//2 进⼊游戏while (1){//3 输出棋盘PrintfChess();//4玩家下棋PlayerMove();//5检查结果winner = CheckGameOver();if (winner != 'c')break;//6电脑下棋ComputerMove();//7检查结果CheckGameOver();winner = CheckGameOver();if (winner != 'c')break;}if (winner == 'x')printf("玩家赢.\n");printf("电脑赢.\n");if (winner == 'h')printf("和棋.\n");}void InitGame(){for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++)chess_board[i][j] = ' ';}}void PrintfChess()//输出棋盘,棋盘的设计可以根据⾃⼰的喜好设计{for (int i = 0; i < ROW; i++){printf("| %c | %c | %c |\n", chess_board[i][0], chess_board[i][1], chess_board[i][2]); if (i < ROW - 1)printf("|---|---|---|\n");}}void PlayerMove()//玩家下棋{printf("玩家落⼦.\n");int row, col;while (1){printf("请输⼊⼀组坐标(下棋位置):>");scanf("%d %d", &row, &col);//检查坐标的有效性if (row < 0 || row > ROW || col < 0 || col > COL){printf("输⼊⾮法,请重新输⼊...");continue;}if (chess_board[row][col] != ' '){printf("输⼊的位置已被占⽤,请重新输⼊...");continue;}chess_board[row][col] = 'x';//x代表玩家下的棋break;}}void ComputerMove()//电脑下棋{srand(time(0));while (1){int row = rand() % ROW;int col = rand() % COL;if (chess_board[row][col] != ' '){continue;}chess_board[row][col] = 'o';//o代表电脑下的棋break;}}/** 'x'代表玩家赢* 'o'代表电脑赢* 'h'代表和棋* 'c'代表继续*/char CheckGameOver()//检测游戏是否结束{//检查⾏for (int i = 0; i < ROW; i++){if (chess_board[i][0] != ' '&& chess_board[i][0] == chess_board[i][1]&& chess_board[i][0] == chess_board[i][2])return chess_board[i][0];}//检查列for (int j = 0; j < COL; j++){if (chess_board[0][j] != ' '&& chess_board[0][j] == chess_board[1][j]&& chess_board[0][j] == chess_board[2][j])return chess_board[0][j];}//检查对⾓线if (chess_board[0][0] != ' '&& chess_board[0][0] == chess_board[1][1]&& chess_board[0][0] == chess_board[2][2])return chess_board[0][0];if (chess_board[0][2] != ' '&& chess_board[0][2] == chess_board[1][1]&& chess_board[0][2] == chess_board[2][0])return chess_board[0][2];//判断是否和棋if (ChessFull())return 'h';return 'c';}bool ChessFull(){for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++){if (chess_board[i][j] == ' ')return false;}}return true;}运⾏测试图:程序的运⾏界⾯我们还可以利⽤system("cls")对界⾯进⾏优化,这样可以使界⾯更加美观。
井字棋策略

一、问题描述井字棋的棋盘是一个九宫格(即3×3的方格),因此通常可以在纸上画一个井字来做棋盘用,井字棋因此得名。
下棋时双方交替向棋盘上布子,每个棋子要落在尚无棋子的方格内。
棋子落下后不能移动,无吃子一说。
当其中任意一方有三个棋子连成一线(横向、纵向或斜向均可)时,即为“胜”,另一方为“负”。
如果棋盘上9个棋格都摆满了棋子,双方都没有连成一线的三子,即为“和棋”。
二、算法分析在对弈问题中,计算机操作的数据对象是每走一步棋后形成的棋盘状态(格局),对每一个格局来说,它的下一步棋都有若干不同的走法,这样一层一层就形成了一个状态空间树。
处于某一格局时,计算机又是如何选择走下一步棋呢? 当然是选择对自己有利的格局,而电脑是如何识别有利的格局?一般是使用一个估价函数,对每个格局进行“估价”,假设估价函数值越大,表示对电脑走棋越有利,那么,电脑在走下一步棋时,只要搜索出估价函数值最大的格局即可。
实际上,很难找到一个准确的函数来完全反映复杂的格局,但希望它尽可能的接近。
在井字棋中,如果计算机赢value = + 1 ,对手赢value = - 1 ,平局value = 0 ,而这些格局可作为博奕树的终端结点;对于非终端结点,电脑走棋会选估价函数值高的格局,当然对手走棋会选函数值低的格局,这样非终端结点的函数值就由其下层结点的这种最大最小交替递归调用得到,称为最小最大搜索算法。
在图1 中,格局B、C 因对手走一步棋即赢,函数值为- 1 ,格局E 因电脑走一步棋即赢,函数值为+ 1 ,格局G平局,函数值为0 ,格局F 为电脑下棋,函数值F = Max( G) = 0 ,格局D 为对手下棋,D =Min(E ,F) = 0 ,格局A 为电脑下棋,A =Max(B ,C) = 0。
下面给出这种最小最大搜索算法中,电脑和对手的走棋程序int comp ( Int &move){int i ,response ,p ;int value = - 2 ; //设临时最大值初始为- ∞if (full () ) return(0) ;//棋盘满为平局if (win-comp () ) return(1) ;//走一步棋,计算机赢for (i = 0 ;i < 9 ;i + + )//测试棋盘上所有方格if (chess[ i ] = = 0) //方格未落子{chess[ i ] = 1 ;//计算机下子为1response = human() ;chess[ i ] = 0 ;//恢复棋盘if (response > value){ value = response ;move = i ; }}return value ;}int human(int &move){int i ,response ,p ;int value = 2 ; //设临时最小值初始为+ ∞+if (full () ) return (0) ;if (win- human() ) return ( - 1) ; //走一步棋,对手赢for (i = 0 ;i < 9 ;i + + )if (chess[ i ] = = 0){chess[ i ] = 2 ; //对手下子为2response = comp (p) ;chess[ i ] [ j ] = 0 ; //恢复棋盘if (response < value){ value = response ;move = I ;}}return value ;}对于一些更加复杂的游戏,如国际象棋、跳棋、五子棋等,要想搜索到终端结点是很困难的,甚至是不可能的,我们可以往下搜索几层,把最低一层看成终端结点,其估价函数值根据对格局的分析近似得出。
Python游戏设计案例实战第9章 游戏实战篇——人机对战井字棋游戏

def main():
computer, human = pieces()
turn = X
board = new_board()
display_board(board)
while not winner(board):
#当返回False继续,否则结束循环
if turn == human:
move = human_move(board, human)
(2)否则,如果有一步棋可以让玩家在本轮获胜,就选那一步走。
(3)否则,电脑机器人应该选择最佳空位置来走。最佳位置就是中间 那个,第二好位置是四个角,剩下的就都算第三好的了。
9.3 对战井字棋游戏设计步骤
1.确定谁先走
#询问玩家你是否先走 def ask_yes_no(question):
response = None while response not in ("y", "n"): #如果输入不是"y", "n",继续重新输入
print("\n玩家你先走.") human = X computer = O else: print("\n电脑先走.") computer = X human = O return computer, human
9.3 对战井字棋游戏设计步骤
2.产生新的保存走棋信息列表和显示棋盘
#产生保存走棋信息列表board def new_board():
board[move] = computer if winner(board) == computer:
print("电脑下棋位置..." ,move) return move # 取消走棋方案 board[move] = EMPTY
Python游戏设计案例实战第9章 游戏实战篇——人机对战井字棋游戏

9.3 对战井字棋游戏设计步骤
3.产生可以合法走棋位置序列 #产生可以合法走棋位置序列(也就是还未下过子位置) def legal_moves(board):
moves = [] for square in range(9):
if board[square] == EMPTY: moves.append(square)
print("\n玩家你先走.") human = X computer = O else: print("\n电脑先走.") computer = X human = O return computer, human
9.3 对战井字棋游戏设计步骤
2.产生新的保存走棋信息列表和显示棋盘
#产生保存走棋信息列表board def new_board():
if board[i]==EMPTY: board2[i]=i
print("\t", board2[0], "|", board2[1], "|", board2[2]) print("\t", "---------") print("\t", board2[3], "|", board2[4], "|", board2[5]) print("\t", "---------") print("\t", board2[6], "|", board2[7], "|", board2[8], "\n")
return moves
9.3 对战井字棋游戏设计步骤
数据结构课程设计报告(井字棋)
目录一、设计课题名 (1)二、设计目的 (1)三、问题描述及需求分析 (1)四、概要设计 (1)五、详细设计 (1)六、测试数据及测试结果 (5)七、课程设计小结 (7)八、用户手册 (8)一、设计课题名井字棋(人机对弈)二、设计目的1、课程设计是《数据结构》课程教学必不可缺的一个重要环节;2、通过课程设计加深课堂教学内容的理解和巩固;3、将《数据结构》课程的教学内容与解决实际问题结合起来,培养理论联系实际的学风;4、提高程序设计能力、培养自学能力;5、提高分析问题、解决问题的能力;6、提高收集资料、查找参考书的能力;7、锻炼书写报告的能力。
三、问题描述及需求分析本设计的主要完成的是井字棋的人机对弈问题,即计算机与人交替落子,当行、列或对角有连续三个相同一方棋时,则判定一方胜利,若无此情形则为和局。
要完成此设计则需一判定胜负函数及一计算机自行落子函数,一旦这两个函数完成则此程序主要部分可完成。
四、概要设计完成此程序需一合理数据结构,因其为井字棋游戏程序则此结构中应包含一存储当前棋局的数组;又因计算机在判定在何位置落子最佳时,需一搜索树因而我在设计时设置了一PARENT域和CHILD域;除了主程序外,它还包括具有以下功能的函数:(1) 棋盘初始化函数:void Init();(2) 打印棋盘函数:void PrintQP();(3) 用户输入落子位置函数:void UserInput();(4) 判断当前棋局是否有一方获胜,并判断哪一方获胜的函数:int IsWin(State s);(5) 评估函数值计算函数:int e_fun(State s);(6) 极大极小值算法主函数:int AutoDone()。
五、详细设计设计步骤:(1) 选定算法;(2) 建立一个简单的应用程序(如字符界面程序)来测试算法;(3) 选定要实现的其他功能(如双人对弈、悔棋、难易级别选定、联机对战等);(4) 实现井字棋程序。
第6讲 棋类游戏-井字棋游戏人机对弈
10
3.2 程序中用到的资源
资源有:快捷键 位图 光标 快捷键、位图 光标、 快捷键 位图、光标 对话框、图标 菜单、字符串 图标、菜单 字符串、 对话框 图标 菜单 字符串 工具栏等。 工具栏
11
位图: IDB_BITMAP1:bmBlackNew.bmp位图,对应于黑棋 IDB_BITMAP1 棋子(玩家)。 IDB_BITMAP2:bmRedNew.bmp位图,对应于红棋 IDB_BITMAP2 棋子(计算机)。 菜单(非向导生成的菜单命令): ID_START:重新开始 ID_START ID_SAVE:保存游戏 ID_SAVE ID_LOAD:载入游戏 ID_LOAD ID_REGRET:悔棋 ID_REGRET ID_ComputerFirst:计算机先下 ID_ComputerFirst ID_Level:难度(易) ID_Level
//视图类自定义成员变量 //QP[i][j]为1表示该位置上是黑方(玩家)棋子, //为-1表示是红方棋子,为0表示没有棋子 int QP[3][3]; //存储棋盘状态 int pre_qp[3][3]; //存储上一步(指计算机和玩家各走了一步)棋盘状态,以便悔棋
8
其他表示游戏状态 游戏状态的成员变量。 游戏状态
5
三、程序界面采用的技术和方法
程序界面具有的特点: 程序界面 单文档应用程序(下一个案例,五子棋,也是单文档应 单文档应用程序 用程序),在视图中绘图。 能保存游戏 保存游戏,能载入游戏 载入游戏。 保存游戏 载入游戏 能悔棋 悔棋(但只能悔一步)。 悔棋 通过一个菜单命令 一个菜单命令来选择先下的两种选项 两种选项:计算机先 一个菜单命令 两种选项 下、玩家先下。 通过一个菜单命令 一个菜单命令来选择两种游戏难度 两种游戏难度:难、易。 一个菜单命令 两种游戏难度
井字棋(人机对战版)
井字棋(⼈机对战版)游戏介绍井字棋,英⽂名叫Tic-Tac-Toe,是⼀种在3*3格⼦上进⾏的连珠游戏,和五⼦棋类似。
然后由分别代表O和X的两个游戏者轮流在格⼦⾥留下标记(⼀般来说先⼿者为X),任意三个标记形成⼀条直线(包括⾏、列、对⾓线、反对⾓线),则为获胜。
解决策略重点在于电脑⽅如何下棋,我们采取估计棋局每个位置的权重,⾸先要对棋局进⾏分类。
---3个为空,重要性最低,权值设置为1 //视为暂时不管---2个空1个对⽅,重要性次低,权值为10 //⼀下三个区别不⼤,可⽐较随意的设置----1个空格1个对⽅1个⼰⽅,重要⾏较低,权值50 ----2个空格1个⼰⽅,重要性较⾼,权值为100---1个空格2个对⽅,重要性次⾼,权值500 //不堵住会输---1个空格2个⼰⽅,重要性最⾼,权值1000 //可以直接赢注意⼏点:1、权值之间的间距可以设⼤⼀点2、对每个空位置,权值等于⾏权值+列权值+对⾓线权值+反对⾓线权值,这4中权值都可以⽤上⾯的估算,但不做改进会出bug考虑如下情况:(1,3)-->(3,1)-->(1,1)-->(2,1)电脑就输了---->--->-->-->⼈获胜关键在于第⼆步,应该选择⼀个⾮⾓的位置,原因在于此时右上⾓位置的权值⼤于中上位置,分析权值的来源右上⾓时,10+10+100(对⾓线⼰⽅),⽽中上时,10+100(⾏⼰⽅),所以同样是2空1⼰⽅时,⼰⽅位于⾏或列的权重应⼤于⼰⽅位于对⾓线。
所以按⾏或列计算时,2空1⼰⽅的权值可改为200代码实现1 #include<stdio.h>2 #include<Windows.h>34const int ROW = 3;5const int COL = 3;6int chessboard[ROW][COL];7int score[ROW][COL];89void Initmap();10void Showmap(); //打印棋局11bool isWin(); //判断是否有⼀⽅获胜12bool isFull(); //判断棋盘是否为满13void PcPlay(); //电脑下棋14void HumanPlay(); //⼈下棋1516int main()17{18 Initmap();19 Showmap();20while ((!isFull()) && (!isWin()))21 {22 HumanPlay();23 system("cls");24 Showmap();25if (isWin())26break;2728 Sleep(500); //模拟实际过程,让电脑慢点,hh29 PcPlay();34if (isFull())35 printf("\n\n平局\n");3637 system("pause");38return0;39}4041void Initmap()42{43for (int i = 0; i < ROW; i++)44for (int j = 0; j < COL; j++)45 chessboard[i][j] = 1;46}4748void Showmap()49{50for (int i = 0; i < ROW; i++)51 {52for (int j = 0; j < COL; j++)53 {54if (chessboard[i][j] == 1) //"1"代表空55 printf("□");56if (chessboard[i][j] == 2) //"2"代表⼈57 printf("■");58if (chessboard[i][j] == 5) //"5"代表电脑59 printf("●");60 }61 printf("\n");62 }63}6465bool isWin()66{67int sum = 0;68for (int i = 0; i < ROW; i++) //对每⾏判断是否获胜 69 {70for (int j = 0; j < COL; j++)71 sum += chessboard[i][j];7273if (sum == 6)74 {75 printf("⼈获胜!\n");76return true;77 }78if (sum == 15)79 {80 printf("电脑获胜!\n");81return true;82 }83 sum = 0;84 }8586for (int j = 0; j < ROW; j++) //对每列判断是否获胜 87 {88for (int i = 0; i < COL; i++)89 sum += chessboard[i][j];9091if (sum == 6)92 {93 printf("⼈获胜!\n");94return true;95 }96if (sum == 15)97 {98 printf("电脑获胜!\n");99return true;100 }105 sum += chessboard[i][i];106if (sum == 6)107 {108 printf("⼈获胜!\n");109return true;110 }111if (sum == 15)112 {113 printf("电脑获胜!\n");114return true;115 }116117 sum = 0;118for (int i = 0; i < ROW; i++) //对反对⾓线判断是否获胜119 sum += chessboard[i][2 - i];120if (sum == 6)121 {122 printf("⼈获胜!\n");123return true;124 }125if (sum == 15)126 {127 printf("电脑获胜!\n");128return true;129 }130131return false;132}133134bool isFull()135{136for (int i = 0; i < ROW; i++)137for (int j = 0; j < COL; j++)138if (chessboard[i][j] == 1)139return false;140return true;141}142143void HumanPlay()144{145int x, y;146 printf("请输⼊棋⼦的横坐标X:");147 scanf_s("%d", &x);148 printf("请输⼊棋⼦的纵坐标Y:");149 scanf_s("%d", &y);150151while (x < 1 || x>3 || y < 1 || y>3)152 {153 printf("\n请正确输⼊!\n");154 printf("x,y均属于1~3\n\n");155156 printf("请输⼊棋⼦的横坐标X:");157 scanf_s("%d", &x);158 printf("请输⼊棋⼦的纵坐标Y:");159 scanf_s("%d", &y);160 }161162while (chessboard[3 - y][x - 1] != 1)163 {164 printf("\n\n该位置已被占⽤!\n");165 printf("请选择正确的位置\n\n");166 Sleep(1000);167168 printf("\n请输⼊棋⼦的横坐标X:");169 scanf_s("%d", &x);170 printf("请输⼊棋⼦的纵坐标Y:");171 scanf_s("%d", &y);176177void PcPlay()178{179int sum = 0;180for (int i = 0; i < ROW; i++)181for (int j = 0; j < COL; j++)182 score[i][j] = 0;183184// 对每⾏进⾏分数统计185for (int i = 0; i < ROW; i++)186 {187for (int j = 0; j < COL; j++)188 sum += chessboard[i][j];189190switch (sum)191 {192case3: //1+1+1;重要性:最低;权重:1193for (int k = 0; k < COL; k++)194 {195if (chessboard[i][k] == 1)196 score[i][k] += 1;197 }198break;199case4: //1+1+2;重要性:次低;权重:10 200for (int k = 0; k < COL; k++)201 {202if (chessboard[i][k] == 1)203 score[i][k] += 10;204 }205break;206case8: //1+2+5;重要性:较低,权值50207for (int k = 0; k < COL; k++)208 {209if (chessboard[i][k] == 1)210 score[i][k] += 50;211 }212break;213case7: //1+1+5;重要性:较⾼;权重:200 214for (int k = 0; k < COL; k++)215 {216if (chessboard[i][k] == 1)217 score[i][k] += 200; //把⾏列的重要性⽐对⾓线⾼218 }219break;220case5: //1+2+2;重要性:次⾼;权重:500 221for (int k = 0; k < COL; k++)222 {223if (chessboard[i][k] == 1)224 score[i][k] += 500;225 }226break;227case11: //1+5+5;重要性:最⾼;权重:1000 228for (int k = 0; k < COL; k++)229 {230if (chessboard[i][k] == 1)231 score[i][k] += 1000;232 }233break;234 }235 sum = 0;236 }237238// 对每列进⾏分数统计239for (int j = 0; j < COL; j++)240 {241for (int i = 0; i < ROW; i++)242 sum += chessboard[i][j];247for (int k = 0; k < COL; k++)248 {249if (chessboard[k][j] == 1)250 score[k][j] += 1;251 }252break;253case4:254for (int k = 0; k < COL; k++)255 {256if (chessboard[k][j] == 1)257 score[k][j] += 10;258 }259break;260case8:261for (int k = 0; k <262 COL; k++)263 {264if (chessboard[k][j] == 1)265 score[k][j] += 50;266 }267break;268case7:269for (int k = 0; k < COL; k++)270 {271if (chessboard[k][j] == 1) //1+1+5;重要性:较⾼;权重:200 272 score[k][j] += 200;273 }274break;275case5:276for (int k = 0; k < COL; k++)277 {278if (chessboard[k][j] == 1)279 score[k][j] += 500;280 }281break;282case11:283for (int k = 0; k < COL; k++)284 {285if (chessboard[k][j] == 1)286 score[k][j] += 1000;287 }288break;289 }290 sum = 0;291 }292293// 对对⾓线进⾏分数统计294for (int i = 0; i < ROW; i++)295 sum += chessboard[i][i];296switch (sum)297 {298case3:299for (int i = 0; i < COL; i++)300 {301if (chessboard[i][i] == 1)302 score[i][i] += 1;303 }304break;305case4:306for (int i = 0; i < COL; i++)307 {308if (chessboard[i][i] == 1)309 score[i][i] += 10;310 }311break;312case8:313for (int i = 0; i < COL; i++)319case7: //1+1+5;权重:100320for (int i = 0; i < COL; i++)321 {322if (chessboard[i][i] == 1)323 score[i][i] += 100;324 }325break;326case5:327for (int i = 0; i < COL; i++)328 {329if (chessboard[i][i] == 1)330 score[i][i] += 500;331 }332break;333case11:334for (int i = 0; i < COL; i++)335 {336if (chessboard[i][i] == 1)337 score[i][i] += 1000;338 }339break;340 }341342// 对反对⾓线进⾏分数统计343 sum = 0;344for (int i = 0; i < ROW; i++)345 sum += chessboard[i][2 - i];346switch (sum)347 {348case3:349for (int i = 0; i < COL; i++)350 {351if (chessboard[i][2 - i] == 1)352 score[i][2 - i] += 1;353 }354break;355case4:356for (int i = 0; i < COL; i++)357 {358if (chessboard[i][2 - i] == 1)359 score[i][2 - i] += 10;360 }361break;362case8:363for (int i = 0; i < COL; i++)364 {365if (chessboard[i][2 - i] == 1)366 score[i][2 - i] += 50;367 }368break;369case7:370for (int i = 0; i < COL; i++)371 {372if (chessboard[i][2 - i] == 1) //1+1+5;权重:100 373 score[i][2 - i] += 100;374 }375break;376case5:377for (int i = 0; i < COL; i++)378 {379if (chessboard[i][2 - i] == 1)380 score[i][2 - i] += 500;381 }382break;383case11:384for (int i = 0; i < COL; i++)390 }391392int maxRow = 0, maxCol = 0;393for (int i = 0; i < ROW; i++)394for (int j = 0; j < COL; j++)395 {396if (score[i][j] > score[maxRow][maxCol]) 397 {398 maxRow = i;399 maxCol = j;400 }401 }402 chessboard[maxRow][maxCol] = 5;403 }。
井字棋实验报告
井字棋实验报告篇一:井字棋实验报告课程:班别小组成员人工智能原理及其应用12商本学号及姓名指导老师实验02井字棋1、总体要求:1.1总体功能要求:利用不同的方法,实现人机对战过程中呈现出不同程度的智能特征:(1)利用极大极小算法、α-β剪枝来提高算法的效率。
(2)使用高级语言,编写一个智能井字棋游戏。
(3)结合极大极小算法的使用方法和α-β剪枝,让机器与人对弈时不但有智能的特征,而且计算的效率也比较高。
1.2.开发平台要求:开发者开发的软件必须能够在不同系统的电脑上正常运行,因此开发平台为:开发环境:JDK1.6开发工具和技术体系:为了此游戏能够很好的在不同系统中运行,因选择javaee进行开发,利用eclipse1.3项目管理要求:(1)项目程序编写过程中要适当的写一些注释,以便下次作业时能够快速的上手和以后的修改:(2)项目程序要保存在一个固定的工作区间;(3)确保代码不要太多冗余2、需求分析:2.1软件的用户需求:井字棋游戏的用户希望游戏除了有一般的功能之外,还可以通过极大极小算法、α-β剪枝等方法是的井字棋游戏能够拥有智能特征,并是的电脑在人机对弈的过程中因玩家的难度选择而体现不同程度的智能状况。
2.2软件的功能需求:本游戏需要实现功能有:(1)游戏的重新设置(2)游戏统计(如:人赢的次数、电脑赢的次数等)(3)游戏的退出(4)不同智能程度下(脑残、懵懂、正常、智能),人机对弈(5)既可以选择难度,也可以选择谁走第一步(人or电脑) 2.3软件的性能需求:井字棋游戏需要以图形界面的形式表现出来,通过点击图标就可以进入游戏;在游戏进行时,人机对弈时电脑能够快速的反应并根据人的上一步动作作出,通过选择“脑残、懵懂、正常、智能”难度选择,电脑以不同程度的智能与人进行游戏对弈。
2.4 运行环境:能够运行java程序的环境(装有jdk 或者jre)2.5 用户界面设计:用gridlayout进行用户界面的设计把界面中分为不同的模块。