🎯每日努力一点点,技术进步看得见
🏠专栏介绍:【C语言步行梯】专栏用于介绍C语言相关内容,每篇文章将通过图片+代码片段+网络相关题目的方式编写,欢迎订阅~~
需求分析
上课摸鱼的时候,我们可以画个九宫格,在里面画上圆圈,或者叉。现在,我们通过C语言实现这个三子棋游戏,实现用户与电脑下棋。
具体实现
主函数体
在主函数体内,我们需要调用一个menu函数,用它提醒用户:输入1开始游戏,输入0退出游戏。接收用户输入后,通过switch语句,执行game()函数或者退出游戏。menu和game函数将在下文中讲解。
int main()
{
int input = 0;
do
{
menu();
printf("请输入您的选择>");
scanf("%d", &input);
switch(input)
{
case 1:
game();//游戏具体实现函数
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("输入有误,请重新输入\n");
}
}while(input);
return 0;
}
菜单实现
首先,我们需要一个菜单,提示用户:输入1可以开始游戏,输入0会退出游戏。我通过封装一个menu函数实现↓↓↓
void menu()
{
printf("*********************************************\n");
printf("************** 1.play 0.exit ***************\n");
printf("*********************************************\n");
}
游戏实现
棋盘初始化
我们通过一个char board[3][3]
来存储棋盘。如果board[i][j]
为空格,表示该位置还没有下棋;如果board[i][j]
存储’*‘(星号),表示该位置用户已经下棋;如果board[i][j]
存储‘#’(井号),表示该位置电脑已经下棋。
但在开始游戏前,我们需要将棋盘数组每个元素都初始化空格。↓↓↓
void initBoard(char board[ROW][COL], int rows, int cols)
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
board[i][j] = ' ';
}
}
}
显示棋盘
在游戏过程中,玩家或者电脑下完棋后,需要显示棋盘。用户才能知道当前棋盘的落子情况。
void displayBoard(char board[ROW][COL], int rows, int cols)
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
printf(" %c ", board[i][j]);
if(j != cols - 1)
printf("|");
else
printf("\n");
}
if(i != rows - 1)
{
for(int j = 0; j < cols; j++)
{
printf("---");
if(j != cols - 1)
printf("|");
else
printf("\n");
}
}
}
}
上方打印棋盘效果如下图所示。
玩家下棋
提示玩家输入下棋的坐标,接收到坐标后,我们需要判断该坐标是否为空格(表示还没有棋子),如果是空格,则下棋成功;如果不是空格,则下棋失败。
void playerAddChess(char board[ROW][COL], int rows, int cols)
{
printf("玩家下棋\n");
displayBoard(board, rows, cols);
int x = 0;
int y = 0;
while (1)
{
printf("请输入下棋坐标>");
scanf("%d %d", &x, &y);
if (x > rows || x <= 0 || y > cols || y <= 0)
{
printf("该坐标超出棋盘边界,请重新输入\n");
continue;
}
if (board[x - 1][y - 1] != ' ')
{
printf("该坐标已经下过棋子,请重新输入\n");
continue;
}
board[x - 1][y - 1] = '*';
break;
}
}
电脑下棋
通过随机数函数生成x,y坐标。如果生成的坐标位置为空格,则电脑下棋完成;如果该坐标已被占用,则重新生成坐标。
void computerAddChess(char board[ROW][COL], int rows, int cols)
{
printf("电脑下棋\n");
int x = 0;
int y = 0;
while(1)
{
x = rand() % 3 + 1;
y = rand() % 3 + 1;
if(board[x][y] != ' ')
continue;
else
{
board[x - 1][y - 1] = '#';
break;
}
}
displayBoard(board, rows, cols);
}
判断棋盘是否已满
假设经过判断,没有三个棋子能连成一条直线,那就无法判断谁赢谁输。若在此时,棋盘已经满了,但还是没有三个棋子练成一条直线,则双方平手(平局)。如下图所示。
因此,我们需要一个函数,用来判断棋盘是否已经满了。如果满了,则游戏结束;没有满则游戏继续。
int isFull(char board[ROW][COL], int rows, int cols)
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
if(board[i][j] == ' ')
return 0;
}
}
return 1;
}
判断输赢
在电脑或者玩家下完棋后,我们需要判断当前状态下,是否有人获胜。根据三子棋的规则,三个棋子连成直线即获胜。下面函数中,如果玩家获胜,则返回’*‘(星号);如果电脑获胜,则返回’#‘(井号);如果棋盘满了,则返回Q
,表示平局;如果没人获胜,棋盘也没满,则游戏继续,返回’C’。
char isWin(char board[ROW][COL], int rows, int cols)
{
//对每一行判断
for(int i = 0; i < rows; i++)
{
if(board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
//对每一列判断
for(int i = 0; i < cols; i++)
{
if(board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
//对角线
if(board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
return board[0][0];
if(board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
return board[0][2];
if(isFull(board, rows, cols))
return 'Q';
return 'C';
}
游戏函数主体
在实现了上述各个函数后,我们只要稍加组织,就可以实现游戏了。
void game()
{
char board[ROW][COL] = { 0 };
initBoard(board, ROW, COL);
char ret = 0;
while (1)
{
playerAddChess(board, ROW, COL);
ret = isWin(board, ROW, COL);
if (ret != 'C')
break;
computerAddChess(board, ROW, COL);
ret = isWin(board, ROW, COL);
if (ret != 'C')
break;
}
switch (ret)
{
case '*':
printf("玩家获胜\n");
break;
case '#':
printf("电脑获胜\n");
break;
case 'Q':
printf("平局\n");
break;
}
}
完整代码
上面代码中主函数中没有加入随机数种子,在下面代码中加入了srand((unsigned int)time(NULL))
,同时对于上面出现ROW、COL的宏定义等也在下方代码整体给出。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void menu()
{
printf("*********************************************\n");
printf("************** 1.play 0.exit ***************\n");
printf("*********************************************\n");
}
void initBoard(char board[ROW][COL], int rows, int cols)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = ' ';
}
}
}
void displayBoard(char board[ROW][COL], int rows, int cols)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
printf(" %c ", board[i][j]);
if (j != cols - 1)
printf("|");
else
printf("\n");
}
if (i != rows - 1)
{
for (int j = 0; j < cols; j++)
{
printf("---");
if (j != cols - 1)
printf("|");
else
printf("\n");
}
}
}
}
void playerAddChess(char board[ROW][COL], int rows, int cols)
{
printf("玩家下棋\n");
displayBoard(board, rows, cols);
int x = 0;
int y = 0;
while (1)
{
printf("请输入下棋坐标>");
scanf("%d %d", &x, &y);
if (x > rows || x <= 0 || y > cols || y <= 0)
{
printf("该坐标超出棋盘边界,请重新输入\n");
continue;
}
if (board[x - 1][y - 1] != ' ')
{
printf("该坐标已经下过棋子,请重新输入\n");
continue;
}
board[x - 1][y - 1] = '*';
break;
}
}
void computerAddChess(char board[ROW][COL], int rows, int cols)
{
printf("电脑下棋\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % 3 + 1;
y = rand() % 3 + 1;
if (board[x - 1][y - 1] != ' ')
continue;
else
{
board[x - 1][y - 1] = '#';
break;
}
}
displayBoard(board, rows, cols);
}
int isFull(char board[ROW][COL], int rows, int cols)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char isWin(char board[ROW][COL], int rows, int cols)
{
//对每一行判断
for (int i = 0; i < rows; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
//对每一列判断
for (int i = 0; i < cols; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
return board[0][0];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
return board[0][2];
if (isFull(board, rows, cols))
return 'Q';
return 'C';
}
void game()
{
char board[ROW][COL] = { 0 };
initBoard(board, ROW, COL);
char ret = 0;
while (1)
{
playerAddChess(board, ROW, COL);
ret = isWin(board, ROW, COL);
if (ret != 'C')
break;
computerAddChess(board, ROW, COL);
ret = isWin(board, ROW, COL);
if (ret != 'C')
break;
}
switch (ret)
{
case '*':
printf("玩家获胜\n");
break;
case '#':
printf("电脑获胜\n");
break;
case 'Q':
printf("平局\n");
break;
}
}
int main()
{
int input = 0;
do
{
menu();
printf("请输入您的选择>");
scanf("%d", &input);
switch (input)
{
case 1:
game();//游戏具体实现函数
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("输入有误,请重新输入\n");
}
} while (input);
return 0;
}
分文件编写
可以创建game.h保存头文件,及各函数的函数声明;game.c保存各个函数的具体实现;main.c中保存主函数。
game.h ↓↓↓
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
//初始化棋盘
void initBoard(char board[ROW][COL], int rows, int cols);
//菜单
void menu();
//打印棋盘
void displayBoard(char board[ROW][COL], int rows, int cols);
//玩家下棋
void playerAddChess(char board[ROW][COL], int rows, int cols);
//电脑下棋
void computerAddChess(char board[ROW][COL], int rows, int cols);
//游戏
void game();
//判断棋盘是否已经满了
int isFull(char board[ROW][COL], int rows, int cols);
//判断是否赢
char isWin(char board[ROW][COL], int rows, int cols);
game.c ↓↓↓
#include "game.h"
void menu()
{
printf("*********************************************\n");
printf("************** 1.play 0.exit ***************\n");
printf("*********************************************\n");
}
void initBoard(char board[ROW][COL], int rows, int cols)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = ' ';
}
}
}
void displayBoard(char board[ROW][COL], int rows, int cols)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
printf(" %c ", board[i][j]);
if (j != cols - 1)
printf("|");
else
printf("\n");
}
if (i != rows - 1)
{
for (int j = 0; j < cols; j++)
{
printf("---");
if (j != cols - 1)
printf("|");
else
printf("\n");
}
}
}
}
void playerAddChess(char board[ROW][COL], int rows, int cols)
{
printf("玩家下棋\n");
displayBoard(board, rows, cols);
int x = 0;
int y = 0;
while (1)
{
printf("请输入下棋坐标>");
scanf("%d %d", &x, &y);
if (x > rows || x <= 0 || y > cols || y <= 0)
{
printf("该坐标超出棋盘边界,请重新输入\n");
continue;
}
if (board[x - 1][y - 1] != ' ')
{
printf("该坐标已经下过棋子,请重新输入\n");
continue;
}
board[x - 1][y - 1] = '*';
break;
}
}
void computerAddChess(char board[ROW][COL], int rows, int cols)
{
printf("电脑下棋\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % 3 + 1;
y = rand() % 3 + 1;
if (board[x - 1][y - 1] != ' ')
continue;
else
{
board[x - 1][y - 1] = '#';
break;
}
}
displayBoard(board, rows, cols);
}
int isFull(char board[ROW][COL], int rows, int cols)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char isWin(char board[ROW][COL], int rows, int cols)
{
//对每一行判断
for (int i = 0; i < rows; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
//对每一列判断
for (int i = 0; i < cols; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
return board[0][0];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
return board[0][2];
if (isFull(board, rows, cols))
return 'Q';
return 'C';
}
void game()
{
char board[ROW][COL] = { 0 };
initBoard(board, ROW, COL);
char ret = 0;
while (1)
{
playerAddChess(board, ROW, COL);
ret = isWin(board, ROW, COL);
if (ret != 'C')
break;
computerAddChess(board, ROW, COL);
ret = isWin(board, ROW, COL);
if (ret != 'C')
break;
}
switch (ret)
{
case '*':
printf("玩家获胜\n");
break;
case '#':
printf("电脑获胜\n");
break;
case 'Q':
printf("平局\n");
break;
}
}
main.c ↓↓↓
int main()
{
int input = 0;
do
{
menu();
printf("请输入您的选择>");
scanf("%d", &input);
switch (input)
{
case 1:
game();//游戏具体实现函数
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("输入有误,请重新输入\n");
}
} while (input);
return 0;
}
🚩这篇文章结束了~~
如果文章中出现了错误,欢迎私信或留言。(๑•̀ㅂ•́)و✧
有任何疑问请评论或私信哦~~o( ̄▽ ̄)ブ