【C语言简陋实现小游戏】井字棋
井字棋小游戏,是类似五子棋的一种棋类玩法:在一个井字棋盘中,双方依次落子,当一位玩家三子连成线,则该玩家获胜。
C语言实现井字棋游戏的界面:
选择序号 1:开始游戏
选择序号 0:退出游戏
选择其他序号:选择错误,需重新选择
即:井字棋游戏,执行代码后可直接进入游戏选择序号,然后执行相应序号的代码
可在do while循环内 使用 switch 语句来实现:
int main()
{
int input = 0;
do
{
//选择菜单
printf("*********************************\n");
printf("******** 1. play ********\n");
printf("******** 0. exit ********\n");
printf("*********************************\n");
printf("请选择序号:>");
scanf("%d", &input);
switch (input)
{
case 1:
//游戏本体函数
game_main();
break;
case 0:
printf("退出成功!");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while(input);
return 0;
}
进入do while循环前,int 定义一个需要输入的整数变量 input。
因为 循环条件大于0 为真,所以可以直接用 input 作为循环条件的判断
**
- input == 1,开始游戏,游戏结束后再次进入循环,可重复游玩
- input == 0,退出游戏,循环条件判断为 假,退出循环,程序结束
- input != 0 && input != 1,选择错误,循环条件判断为 真 ,进入下次循环
**
井字棋基本逻辑 和 代码 捋清楚之后,就可以写游戏的本体函数
我这里函数名 是 game_main()
下井字棋,需要一个二维数组来存放棋子,棋子和棋盘的显示,成如下形式:
首先,定义一个字符数组,并需要对字符数组进行全为 ‘ ’ 的初始化
char board[3][3];
//初始化 数组 函数
InitiBoard(board, 3, 3);
定义一个 InitiBoard 函数来进行字符数组初始化 对数组遍历赋值
void InitiBoard(char board[3][3], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; //遍历数组元素 赋值 ‘ ’ } } }
初始化之后,将字符数组元素 和 棋盘打印出来
DispalyBoard(board, 3, 3);
定义一个 InitiBoard 函数 对 字符数组(棋子)和 棋盘 打印显示
void DisplayBoard(char board[3][3], 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) { int j = 0; for (j = 0; j < col; j++) { //棋子行 之间 需要分界线 printf("---"); if (j < col - 1) printf("|"); } printf("\n"); } } }
上边 两个函数 在game_main() 游戏本体函数 使用后
选择序号 1 屏幕中显示:
接下来,由 玩家 和 电脑 依次下棋落子,落子后打印出棋盘,直到游戏结束
玩家落子 为 ‘ * ’,电脑落子 为 ‘ # ’
且 玩家落子的坐标 需合理
即,玩家 和 电脑 落子的执行 和 打印棋盘 需一直循环 除非游戏结束
每次落子后 我们对字符数组中的 棋子 进行计算,判断游戏是否结束
共自定义三个函数
玩家落子:PlayerMove()
电脑落子:ComputerMove()
判断游戏是否结束:IsWin()
char ret;
while (1)
{
//玩家下棋
PlayerMove(board, 3, 3);
DisplayBoard(board, 3, 3);
//判断 游戏的进程 游戏是否结束
ret = IsWin(board, 3, 3);
if (ret != 'C')
break;
//电脑下棋
ComputerMove(board, 3, 3);
DisplayBoard(board, 3, 3);
//判断 游戏的进程 游戏是否结束
ret = IsWin(board, 3, 3);
if (ret != 'C')
break;
//设定 IsFull() 函数
//返回值为 '*' 玩家赢
//返回值为 '#' 电脑赢
//返回值为 'Q' 平局
//返回值为 'C' 游戏继续
}
玩家落子 的函数:PlayerMove()
void PlayerMove(char board[3][3], int row, int col) { int x = 0; int y = 0; printf("玩家走:>\n"); while (1) { printf("请输入坐标:>"); scanf("%d %d", &x, &y); //判断玩家落子是否在 棋盘内 即,玩家落子是否合理 if (x >= 1&& x <= row && y >= col && y <= 3) { //判断 玩家落子坐标是否已经被落子 if (board[x-1][y-1] == ' ') { board[x-1][y-1] = '*'; break; } //玩家落子坐标已被落子,重新输入坐标 else printf("坐标占用,请重新输入!\n"); } //玩家落子坐标非法,重新输入坐标 else printf("非法坐标,请重新输入!\n"); } }
电脑自动落子 函数:ComputerMove()
void ComputerMove(char board[3][3], int row, int col) { //最简单的下棋 电脑 无算法,完全随机落子 printf("电脑走:>\n"); while (1) { int x = rand() % row; //用 rand 随机生成坐标x int y = rand() % col; //用 rand 随机生成坐标y //rand 函数取随机值 的使用 可详见 本人另一篇 博客,链接放在最下方 //判断 电脑落子坐标是否已经被落子 if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }
判断棋局进程 函数:IsWin()
在判断棋局的进程时,若无人获胜,还需判断棋盘是否下满,下满则平局,未下满则游戏继续( 需 自定义 IsFull() 函数 判断棋盘是否下满
)//设定 //返回值为 '*' 玩家赢 //返回值为 '#' 电脑赢 //返回值为 'Q' 平局 //返回值为 'C' 游戏继续 char IsWin(char board[3][3], int row, int col) { int i = 0; int j = 0; //循环判断 1-3 行 的棋子是否相同 for (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]; } //循环判断 1-3 列 的棋子是否相同 for (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]; } //循环判断 2条对角线 的棋子是否相同 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]; //判断平局 // IsFull 返回值 为 1 棋盘满 平局 // 返回值 为 0 棋盘未满 游戏继续 int ret = IsFull(board, row, col); if (ret == '1') return 'Q'; return 'C'; }
棋盘是否下满的判断 函数:IsFull()
int IsFull(char board[3][3], int row, int col) { int i = 0; int j = 0; //遍历棋盘 判断 是否数组中是否有元素 为 ‘ ’ //若有 返回 0,表示棋盘未满 //若无 返回 1,表示棋盘已满 for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == ' ') { return '0'; break; } } } return '1'; //上 循环中 未返回 0 ; 则返回 1 }
接下来,由 ret 的值 判断 输赢
if (ret == '*')
printf("玩家赢了!\n");
else if (ret == '#')
printf("电脑赢了!\n");
else
printf("平局!\n");
DisplayBoard(board, 3, 3);
printf("\n");
至此,game_main() 内容为:
void game_main()
{
int j = 0;
int i = 0;
char ret;
char board[3][3];
//初始化 数组
InitiBoard(board, 3, 3);
//打印 棋盘
DisplayBoard(board, 3, 3);
while (1)
{
//玩家下棋
PlayerMove(board, 3, 3);
DisplayBoard(board, 3, 3);
//判断 棋局输赢
ret = IsWin(board, 3, 3);
if (ret != 'C')
break;
//电脑下棋
ComputerMove(board, 3, 3);
DisplayBoard(board, 3, 3);
//判断 棋局输赢
ret = IsWin(board, 3, 3);
if (ret != 'C')
break;
}
if (ret == '*')
printf("玩家赢了!\n");
else if (ret == '#')
printf("电脑赢了!\n");
else
printf("平局!\n");
DisplayBoard(board, 3, 3);
printf("\n");
}
游戏所需函数 等 编写完成;
可整合至项目中:
游戏各自定义函数 代码文件:chess_function.c
#include "chess_10_8.h"
//初始化棋盘 函数
void InitiBoard(char board[3][3], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//打印棋盘 函数
void DisplayBoard(char board[3][3], 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)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
//玩家落子 函数
void PlayerMove(char board[3][3], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家走:>\n");
while (1)
{
printf("请输入坐标:>");
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("坐标占用,请重新输入!\n");
}
else
printf("非法坐标,请重新输入!\n");
}
}
//电脑落子 函数
void ComputerMove(char board[3][3], int row, int col)
{
printf("电脑走:>\n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
int IsFull(char board[3][3], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return '0';
break;
}
}
}
return '1';
}
//返回值为 '*' 玩家赢
//返回值为 '#' 电脑赢
//返回值为 'Q' 平局
//返回值为 'C' 游戏继续
//判断棋局输赢 函数
char IsWin(char board[3][3], int row, int col)
{
int i = 0;
int j = 0;
//判断 行
for (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];
}
//判断 列
for (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];
//判断 平局
// IsFull 返回值 为 1 棋盘满 平局
// 返回值 为 0 期盼未满 游戏继续
int ret = IsFull(board, row, col);
if (ret == '1')
return 'Q';
return 'C';
}
//游戏主体函数
void game_main()
{
int j = 0;
int i = 0;
char ret;
char board[3][3];
//初始化 数组
InitiBoard(board, 3, 3);
//打印 棋盘
DisplayBoard(board, 3, 3);
while (1)
{
//玩家下棋
PlayerMove(board, 3, 3);
DisplayBoard(board, 3, 3);
ret = IsWin(board, 3, 3);
if (ret != 'C')
break;
//电脑下棋
ComputerMove(board, 3, 3);
DisplayBoard(board, 3, 3);
if (ret != 'C')
break;
}
if (ret == '*')
printf("玩家赢了!\n");
else if (ret == '#')
printf("电脑赢了!\n");
else
printf("平局!\n");
DisplayBoard(board, 3, 3);
printf("\n");
}
游戏各自定义函数的引用 头文件:chess_function.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void InitiBoard(char board[3][3], int row, int col); //初始化数组的函数
void DisplayBoard(char board[3][3], int row, int col); //打印棋盘的函数
void PlayerMove(char board[3][3], int row, int col); //玩家下棋
void ComputerMove(char board[3][3], int row, int col); //电脑下棋
char IsWin(char board[3][3], int row, int col); //判断输赢的返回值
int IsFull(char board[3][3], int row, int col); //判断棋盘 是否满
游戏的主函数文件:chess_game_main.c
#include "chess_10_8.h"
int main()
{
int input = 0;
//随机值前的调用
srand((unsigned int)time(NULL));
do
{
//选择菜单
printf("*********************************\n");
printf("******** 1. play ********\n");
printf("******** 0. exit ********\n");
printf("*********************************\n");
printf("请选择序号:>");
scanf("%d", &input);
switch (input)
{
case 1:
//游戏本体函数
game_main();
break;
case 0:
printf("退出成功!");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while(input);
return 0;
}
游戏实现
Gitee :https://gitee.com/xyt-g/problem-of-learning/tree/%E5%AD%A6%E4%B9%A0%E6%97%B6%E5%9C%B0%E7%BB%83%E4%B9%A0%EF%BC%8C%E8%AE%B0%E5%BF%86/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BF%86/%E4%BA%95%E5%AD%97%E6%A3%8B%E6%B8%B8%E6%88%8F