1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > C语言实现小游戏之井字棋

C语言实现小游戏之井字棋

时间:2019-10-12 22:17:29

相关推荐

C语言实现小游戏之井字棋

目录

前言

一、井字棋游戏的主流程

二、游戏部分

1.游戏函数

2.初始化棋盘

3.打印棋盘

4.玩家下棋

5.电脑下棋(两个难度等级)

6.判断游戏是否结束

三、 源码展示

总结

前言

这是我在学习C语言的过程中自己编写的一个小游戏,现在将自己的思路(主要以流程图形式和代码中的注释表达)和具体代码以及运行结果分享出来以供大家学习参考。

一、井字棋游戏的主流程

主流程的流程图:

主函数代码:

int main(){//设置随机值起始值srand((unsigned int)time(NULL));int input = 0;printf("游戏加载中,请耐心等候……\n");Sleep(2000);do{menu();//主菜单printf("请选择:>\n");//玩家选择scanf("%d", &input);switch (input)//判断玩家是否进行游戏以及是否输入合法选项{case 1:game();//游戏break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");}} while (input);//do while循环至少进行一次选择。当玩家输入非法字符或者已经进行了一局游戏后可以回到主菜单,询问玩家是否继续玩游戏。return 0;}

二、游戏部分

游戏部分流程图:

1.游戏函数

游戏程序:

//游戏程序void game(){int ret1 = Level();char ret2 = '\0';char board[ROW][COL] = { 0 };printf("游戏开始!\n");//初始化棋盘的函数InitBoard(board, ROW, COL);//打印棋盘的函数DisplayBoard(board, ROW, COL);//下棋while (1)//玩家下一步电脑下一步一直到游戏结束(两人中有一人胜利或者平局),才能结束循环{//玩家下棋PlayerMove(board, ROW, COL);//判断是否结束ret2 = IsWin(board, ROW, COL);if (ret2 != 'C'){break;}DisplayBoard(board, ROW, COL);//电脑下棋//简单(电脑下棋位置完全随机)if (1 == ret1){ComputerMove1(board, ROW, COL);}//初级(电脑具有堵住玩家和自己取胜的简单思路)else if (2 == ret1){ComputerMove2(board, ROW, COL);}//其他,暂时未优化(期望是电脑的走棋位置更加优化,让电脑也学会做棋)else if (3 == ret1){printf("正在开发,敬请期待\n");}//判断是否结束ret2 = IsWin(board, ROW, COL);if (ret2 != 'C'){break;}DisplayBoard(board, ROW, COL);}if ('*' == ret2){printf("玩家赢!\n");}else if ('#' == ret2){printf("电脑赢!\n");}else{printf("平局!\n");}DisplayBoard(board, ROW, COL);}

主菜单:

void menu(){printf("*******************************\n");printf("********** 1.play ***********\n");printf("********** 0.exit ***********\n");printf("*******************************\n");}

游戏难度菜单:

//选择游戏难度int Level(){int input = 0;int level = 0;while (1){printf("请选择游戏难度:>\n");printf("***********************************\n");printf("********1.简单*********\n");printf("********2.初级*********\n");printf("******** 3.中级(未开发) *********\n");printf("*************敬请期待**************\n");printf("***********************************\n");scanf("%d", &input);switch (input){case 1:return 1;break;case 2:return 2;break;case 3:return 3;break;default:printf("选择错误,请重新选择:>\n");break;}}return 0;}

2.初始化棋盘

//初始化棋盘void InitBoard(char board[ROW][COL],int row,int col){int i = 0;int j = 0;for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){board[i][j] = ' ';}}}

3.打印棋盘

//打印棋盘void DisplayBoard(char board[ROW][COL],int row,int col){int i = 0;int j = 0;for (i = 0; i < row;i++){for (j = 0; j < col; j++){printf(" %c ", board[i][j]);if (j < col - 1){printf("|");}}printf("\n");if (i < row - 1){for (j = 0; j < col; j++){printf("---");if (j < col - 1){printf("|");}}printf("\n");}}}

4.玩家下棋

//玩家回合void PlayerMove(char board[ROW][COL], int row, int col){int x = 0;int y = 0;printf("到玩家下棋!\n");printf("玩家请输入要下棋的坐标(例如:1 1):>");while (1){scanf("%d %d", &x, &y);//坐标范围是否合法的判断if (x >= 1 && x <= row && y >= 1 && y <= col){if (' ' == board[x - 1][y - 1])//判断玩家所选择的坐标是否已经被占{board[x - 1][y - 1] = '*';//玩家在进行游戏时默认坐标是行为1到3,列为1到3。这与数组的下标从0开始不同,因此要将玩家输入的值进行-1的处理才能达到效果。break;}else{printf("该坐标已经被占,请重新选择:>");}}else{printf("输入坐标非法,请重新输入:>");}}}

5.电脑下棋(两个难度等级)

第一个等级:

//第一版,随机落下一子(简单)void ComputerMove1(char board[ROW][COL], int row, int col){printf("电脑下棋\n");while (1){int n = 0;int m = 0;n = rand() % row;//0-2m = rand() % col;if (board[n][m] == ' '){board[n][m] = '#';break;}}}

第二个等级:

//优化版//电脑落子有三种可能://①下一步可以胜利(在自己有两个棋子相连的情况下落下一子达成三连)//②堵住对方快要胜利的棋子(未出现①时,若对方出现两子相连的情况及时堵住)//③随机落下一枚棋子(在①②都未出现时,在棋盘中“随机落下一子”,要保证该位置周围八个位置有对方棋子,避免成为“废棋”)//以上三种情况优先级由高到低//改良后,第二版(初级)int ComputerMove2(char board[ROW][COL], int row, int col){int i = 0;int j = 0;printf("电脑下棋\n");//模拟人类思考时间Sleep(2000);//情况①//行判断:for (int i = 0; i < ROW; i++){if (board[i][0] == board[i][1] && ' ' == board[i][2] && '#' == board[i][0]){board[i][2] = '#';return 0;}if (board[i][0] == board[i][2] && ' ' == board[i][1] && '#' == board[i][0]){board[i][1] = '#';return 0;}if (board[i][1] == board[i][2] && ' ' == board[i][0] && '#' == board[i][1]){board[i][0] = '#';return 0;}}//列判断for (int j = 0; j < COL; j++){if (board[0][j] == board[1][j] && ' ' == board[2][j] && '#' == board[1][j]){board[2][j] = '#';return 0;}if (board[0][j] == board[2][j] && ' ' == board[1][j] && '#' == board[2][j]){board[1][j] = '#';return 0;}if (board[1][j] == board[2][j] && ' ' == board[0][j] && '#' == board[2][j]){board[0][j] = '#';return 0;}}//对角线判断if (board[0][0] == board[1][1] && ' ' == board[2][2] && '#' == board[0][0]){board[2][2] = '#';return 0;}if (board[0][0] == board[2][2] && ' ' == board[1][1] && '#' == board[0][0]){board[1][1] = '#';return 0;}if (board[2][2] == board[1][1] && ' ' == board[1][1] && '#' == board[2][2]){board[1][1] = '#';return 0;}if (board[0][2] == board[1][1] && ' ' == board[2][0] && '#' == board[0][2]){board[2][0] = '#';return 0;}if (board[0][2] == board[2][0] && ' ' == board[1][1] && '#' == board[0][2]){board[1][1] = '#';return 0;}if (board[2][0] == board[1][1] && ' ' == board[0][2] && '#' == board[2][0]){board[0][2] = '#';return 0;}//情况②//行判断:for (int i = 0; i < ROW; i++){if (board[i][0] == board[i][1] && ' ' == board[i][2] && '*' == board[i][0]){board[i][2] = '#';return 0;}if (board[i][0] == board[i][2] && ' ' == board[i][1] && '*' == board[i][0]){board[i][1] = '#';return 0;}if (board[i][1] == board[i][2] && ' ' == board[i][0] && '*' == board[i][1]){board[i][0] = '#';return 0;}}//列判断for (int j = 0; j < COL; j++){if (board[0][j] == board[1][j] && ' ' == board[2][j] && '*' == board[1][j]){board[2][j] = '#';return 0;}if (board[0][j] == board[2][j] && ' ' == board[1][j] && '*' == board[2][j]){board[1][j] = '#';return 0;}if (board[1][j] == board[2][j] && ' ' == board[0][j] && '*' == board[2][j]){board[0][j] = '#';return 0;}}//对角线判断if (board[0][0] == board[1][1] && ' ' == board[2][2] && '*' == board[0][0]){board[2][2] = '#';return 0;}if (board[0][0] == board[2][2] && ' ' == board[1][1] && '*' == board[0][0]){board[1][1] = '#';return 0;}if (board[2][2] == board[1][1] && ' ' == board[1][1] && '*' == board[2][2]){board[1][1] = '#';return 0;}if (board[0][2] == board[1][1] && ' ' == board[2][0] && '*' == board[0][2]){board[2][0] = '#';return 0;}if (board[0][2] == board[2][0] && ' ' == board[1][1] && '*' == board[0][2]){board[1][1] = '#';return 0;}if (board[2][0] == board[1][1] && ' ' == board[0][2] && '*' == board[2][0]){board[0][2] = '#';return 0;}//情况③else{int n = 0;int m = 0;while (1){n = rand() % row;m = rand() % col;int ret = IsHave(board, row, col, n, m);if (' ' == board[n][m] && ret){board[n][m] = '#';break;}}}return 0;}

第二个等级中判断所选位置周围八个位置是否有玩家的棋子:

//判断该位置周围的八个位置是否有玩家的棋子//如果有,则返回 1//如果没有,则返回 0int IsHave(char board[ROW][COL], int row, int col,int x,int y){if ('*' == board[x - 1][y - 1] || '*' == board[x - 1][y] || '*' == board[x - 1][y + 1] ||'*' == board[x][y - 1] || '*' == board[x][y] || '*' == board[x][y + 1] ||'*' == board[x + 1][y - 1] || '*' == board[x + 1][y] || '*' == board[x + 1][y + 1]){return 1;}else{return 0;}}

6.判断游戏是否结束

//如果电脑胜利就返回'#'//如果玩家胜利就返回'*'//如果平局就返回'Q'//打印出结果。//如果有以上一种情况就break结束循环//如果没有就继续返回'C'//无论电脑还是玩家胜利的情况只有://①行一样//②列一样//③对角线一样char IsWin(char board[ROW][COL], int row, int col){//有一方赢了//行判断:int i = 0;for (int i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' '){return board[i][1];}}//列判断:int j = 0;for (int j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' '){return board[1][j];}}//对角线判断:if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[1][1];}if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){return board[1][1];}//平局else if (IsDraw(board,row,col))return 'Q';//继续elsereturn 'C';}

判断是否为平局:

//是否是平局:平局返回1,否则返回0int IsDraw(char board[ROW][COL], int row, int col){int i = 0;int j = 0;for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (' ' == board[i][j])return 0;}}return 1;}

三、 运行展示

演示时我选择了改良版的难度

从图中可以看到在我故意走偏的情况下,电脑是成功赢了这一局游戏。

四、源码展示

为了方便阅读代码,我将这个程序的代码分为了三个部分(三个文件)。

为了方便大家的使用和优化,我将整个代码放在下文:

game.h(游戏代码的实现)

//游戏代码的声明(函数声明,符号定义)#include<stdio.h>#include<stdlib.h>#include<time.h>#include<Windows.h>//通过宏定义行数和列数之后再改进代码,进一步实现五子棋、N子棋时,也只需要改变宏定义处的内容非常的方便。#define ROW 3#define ROW 3#define COL 3//初始化棋盘void InitBoard(char board[ROW][COL], int row, int col);//打印棋盘void DisplayBoard(char board[ROW][COL], int row, int col);//玩家下棋void PlayerMove(char board[ROW][COL],int row,int col);//电脑下棋//简单void ComputerMove1(char board[ROW][COL], int row, int col);//初级int ComputerMove2(char board[ROW][COL],int row,int col);//判断该位置周围的八个位置是否有玩家的棋子//如果有,则返回 1//如果没有,则返回 0int IsHave(char board[ROW][COL], int row, int col, int x, int y);//判断是否胜利char IsWin(char board[ROW][COL], int row, int col);//是否是平局int IsDraw(char board[ROW][COL], int row, int col);

test.c(菜单和主函数,测试游戏的逻辑)

#define _CRT_SECURE_NO_WARNINGS//三子棋游戏//测试游戏的逻辑#include"game.h"//游戏菜单void menu(){printf("*******************************\n");printf("********** 1.play ***********\n");printf("********** 0.exit ***********\n");printf("*******************************\n");}//选择游戏难度int Level(){int input = 0;int level = 0;while (1){printf("请选择游戏难度:>\n");printf("***********************************\n");printf("********1.简单*********\n");printf("********2.初级*********\n");printf("******** 3.中级(未开发) *********\n");printf("*************敬请期待**************\n");printf("***********************************\n");scanf("%d", &input);switch (input){case 1:return 1;break;case 2:return 2;break;case 3:return 3;break;default:printf("选择错误,请重新选择:>\n");break;}}return 0;}//游戏程序void game(){int ret1 = Level();char ret2 = '\0';char board[ROW][COL] = { 0 };printf("游戏开始!\n");//初始化棋盘的函数InitBoard(board, ROW, COL);//打印棋盘的函数DisplayBoard(board, ROW, COL);//下棋while (1){//玩家下棋PlayerMove(board, ROW, COL);//判断是否结束ret2 = IsWin(board, ROW, COL);if (ret2 != 'C'){break;}DisplayBoard(board, ROW, COL);//电脑下棋//简单(电脑下棋位置完全随机)if (1 == ret1){ComputerMove1(board, ROW, COL);}//初级(电脑具有堵住玩家和自己取胜的简单思路)else if (2 == ret1){ComputerMove2(board, ROW, COL);}//其他,暂时未优化(期望是电脑的走棋位置更加优化,让电脑也学会做棋)else if (3 == ret1){printf("正在开发,敬请期待\n");}//判断是否结束ret2 = IsWin(board, ROW, COL);if (ret2 != 'C'){break;}DisplayBoard(board, ROW, COL);}if ('*' == ret2){printf("玩家赢!\n");}else if ('#' == ret2){printf("电脑赢!\n");}else{printf("平局!\n");}DisplayBoard(board, ROW, COL);}int main(){//设置随机值起始值srand((unsigned int)time(NULL));int input = 0;printf("游戏加载中,请耐心等候……\n");Sleep(2000);do{menu();printf("请选择:>\n");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");}} while (input);return 0;}

game.h(游戏代码的声明(函数声明,符号定义))

#define _CRT_SECURE_NO_WARNINGS//游戏代码的实现#include"game.h"//初始化棋盘void InitBoard(char board[ROW][COL],int row,int col){int i = 0;int j = 0;for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){board[i][j] = ' ';}}}//打印棋盘void DisplayBoard(char board[ROW][COL],int row,int col){int i = 0;int j = 0;for (i = 0; i < row;i++){for (j = 0; j < col; j++){printf(" %c ", board[i][j]);if (j < col - 1){printf("|");}}printf("\n");if (i < row - 1){for (j = 0; j < col; j++){printf("---");if (j < col - 1){printf("|");}}printf("\n");}}}//玩家回合void PlayerMove(char board[ROW][COL], int row, int col){int x = 0;int y = 0;printf("到玩家下棋!\n");printf("玩家请输入要下棋的坐标(例如:1 1):>");while (1){scanf("%d %d", &x, &y);//坐标范围是否合法的判断if (x >= 1 && x <= row && y >= 1 && y <= col){if (' ' == board[x - 1][y - 1]){board[x - 1][y - 1] = '*';break;}else{printf("该坐标已经被占,请重新选择:>");}}else{printf("输入坐标非法,请重新输入:>");}}}//判断该位置周围的八个位置是否有玩家的棋子//如果有,则返回 1//如果没有,则返回 0int IsHave(char board[ROW][COL], int row, int col,int x,int y){if ('*' == board[x - 1][y - 1] || '*' == board[x - 1][y] || '*' == board[x - 1][y + 1] ||'*' == board[x][y - 1] || '*' == board[x][y] || '*' == board[x][y + 1] ||'*' == board[x + 1][y - 1] || '*' == board[x + 1][y] || '*' == board[x + 1][y + 1]){return 1;}else{return 0;}}//电脑回合//优化版//电脑落子有三种可能://①下一步可以胜利(在自己有两个棋子相连的情况下落下一子达成三连)//②堵住对方快要胜利的棋子(未出现①时,若对方出现两子相连的情况及时堵住)//③随机落下一枚棋子(在①②都未出现时,在棋盘中“随机落下一子”,要保证该位置周围八个位置有对方棋子,避免成为“废棋”)//以上三种情况优先级由高到低//第一版,随机落下一子(简单)void ComputerMove1(char board[ROW][COL], int row, int col){printf("电脑下棋\n");while (1){int n = 0;int m = 0;n = rand() % row;//0-2m = rand() % col;if (board[n][m] == ' '){board[n][m] = '#';break;}}}//改良后,第二版(初级)int ComputerMove2(char board[ROW][COL], int row, int col){int i = 0;int j = 0;printf("电脑下棋\n");//模拟人类思考时间Sleep(2000);//情况①//行判断:for (int i = 0; i < ROW; i++){if (board[i][0] == board[i][1] && ' ' == board[i][2] && '#' == board[i][0]){board[i][2] = '#';return 0;}if (board[i][0] == board[i][2] && ' ' == board[i][1] && '#' == board[i][0]){board[i][1] = '#';return 0;}if (board[i][1] == board[i][2] && ' ' == board[i][0] && '#' == board[i][1]){board[i][0] = '#';return 0;}}//列判断for (int j = 0; j < COL; j++){if (board[0][j] == board[1][j] && ' ' == board[2][j] && '#' == board[1][j]){board[2][j] = '#';return 0;}if (board[0][j] == board[2][j] && ' ' == board[1][j] && '#' == board[2][j]){board[1][j] = '#';return 0;}if (board[1][j] == board[2][j] && ' ' == board[0][j] && '#' == board[2][j]){board[0][j] = '#';return 0;}}//对角线判断if (board[0][0] == board[1][1] && ' ' == board[2][2] && '#' == board[0][0]){board[2][2] = '#';return 0;}if (board[0][0] == board[2][2] && ' ' == board[1][1] && '#' == board[0][0]){board[1][1] = '#';return 0;}if (board[2][2] == board[1][1] && ' ' == board[1][1] && '#' == board[2][2]){board[1][1] = '#';return 0;}if (board[0][2] == board[1][1] && ' ' == board[2][0] && '#' == board[0][2]){board[2][0] = '#';return 0;}if (board[0][2] == board[2][0] && ' ' == board[1][1] && '#' == board[0][2]){board[1][1] = '#';return 0;}if (board[2][0] == board[1][1] && ' ' == board[0][2] && '#' == board[2][0]){board[0][2] = '#';return 0;}//情况②//行判断:for (int i = 0; i < ROW; i++){if (board[i][0] == board[i][1] && ' ' == board[i][2] && '*' == board[i][0]){board[i][2] = '#';return 0;}if (board[i][0] == board[i][2] && ' ' == board[i][1] && '*' == board[i][0]){board[i][1] = '#';return 0;}if (board[i][1] == board[i][2] && ' ' == board[i][0] && '*' == board[i][1]){board[i][0] = '#';return 0;}}//列判断for (int j = 0; j < COL; j++){if (board[0][j] == board[1][j] && ' ' == board[2][j] && '*' == board[1][j]){board[2][j] = '#';return 0;}if (board[0][j] == board[2][j] && ' ' == board[1][j] && '*' == board[2][j]){board[1][j] = '#';return 0;}if (board[1][j] == board[2][j] && ' ' == board[0][j] && '*' == board[2][j]){board[0][j] = '#';return 0;}}//对角线判断if (board[0][0] == board[1][1] && ' ' == board[2][2] && '*' == board[0][0]){board[2][2] = '#';return 0;}if (board[0][0] == board[2][2] && ' ' == board[1][1] && '*' == board[0][0]){board[1][1] = '#';return 0;}if (board[2][2] == board[1][1] && ' ' == board[1][1] && '*' == board[2][2]){board[1][1] = '#';return 0;}if (board[0][2] == board[1][1] && ' ' == board[2][0] && '*' == board[0][2]){board[2][0] = '#';return 0;}if (board[0][2] == board[2][0] && ' ' == board[1][1] && '*' == board[0][2]){board[1][1] = '#';return 0;}if (board[2][0] == board[1][1] && ' ' == board[0][2] && '*' == board[2][0]){board[0][2] = '#';return 0;}//情况③else{int n = 0;int m = 0;while (1){n = rand() % row;m = rand() % col;int ret = IsHave(board, row, col, n, m);if (' ' == board[n][m] && ret){board[n][m] = '#';break;}}}return 0;}//是否是平局:平局返回1,否则返回0int IsDraw(char board[ROW][COL], int row, int col){int i = 0;int j = 0;for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (' ' == board[i][j])return 0;}}return 1;}//如果电脑胜利就返回'#'//如果玩家胜利就返回'*'//如果平局就返回'Q'//打印出结果。//如果有以上一种情况就break结束循环//如果没有就继续返回'C'//无论电脑还是玩家胜利的情况只有://①行一样//②列一样//③对角线一样char IsWin(char board[ROW][COL], int row, int col){//有一方赢了//行:int i = 0;for (int i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' '){return board[i][1];}}//列:int j = 0;for (int j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' '){return board[1][j];}}//对角线:if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[1][1];}if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){return board[1][1];}//平局else if (IsDraw(board,row,col))return 'Q';//继续elsereturn 'C';}

总结

以上就是今天要讲的内容,本文简单的展示了井字棋小游戏的C语言实现,作者编写代码的思路以及具体代码都在文章中。当然这个井字棋小游戏还有很大的优化空间,后期作者也会进一步对它进行优化,如果您有什么好的想法或者建议也可以向作者提出。

本文的作者也只是一个正在学习C语言等编程知识的萌新,若这篇文章中有哪些不正确的内容,请在评论区向作者指出(也可以私信作者),欢迎大佬们指点,也欢迎其他正在学习C语言的萌新和作者进行交流。

最后,如果本篇文章对你有所启发的话,也希望可以支持支持作者,后续作者也会定期更新学习记录。谢谢大家!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。