三子棋
这个项目是B站鹏哥C语言的课程中。数组部分的实战代码。
博主只是跟着学跟着写的。
整体其实并不是很复杂,将最复杂的game模块进行了独立编写,所以出现了game.c和game.h。
刚入手时需要注意的是一定不要想这个项目有多复杂。
编写步骤
- 理思路(整体流程)
项目进入需要的界面。+ 功能选择。 将这些写完再考虑下一步。
功能选择: 进入游戏 || 退出游戏 || 输入错误。
-
游戏准备 (将以下出现的小模块都函数来写。)
(1) 需要棋盘,+ 初始化棋盘。 -->二维数组
(2) 棋盘的显示。
-
游戏开始
(1) 玩家下棋
(2) 电脑下棋
(3)每次下完展示棋盘
-
结果判断
(1) 玩家赢返回"*"
(2) 电脑赢返回"#"
(3) 平局返回"Q"
(4) 继续返回"C"
-
整理、解决问题(debug)
三子棋代码
以下是我通过调试的代码。(环境:win10,编译器:Clion)
运行文件main.c
//
// Created by Tian_baby on 2021/12/29.
//
#include "game.h"
//打印初识目录界面
void menu(){
printf("*****************************\n");
printf("**** 1. play 0. exit ****\n");
printf("*****************************\n");
}
//游戏的实现
void game(){
// 定义数组来存储棋盘
char board[ROW][COL] = {0};
char res = 0;
//初始化棋盘都是空格
InitBoard(board,ROW,COL);
//打印棋盘
DisplayBoard(board,ROW,COL);
while(1){
PlayerMove(board,ROW,COL);//玩家下棋
DisplayBoard(board,ROW,COL);//展示棋盘情况
res = JudgeWin(board,ROW,COL);
if(res!='C') break; //结果不等于C代表结束了
ComputerMove(board,ROW,COL);// 电脑下棋
DisplayBoard(board,ROW,COL);//展示棋盘的情况
res = JudgeWin(board,ROW,COL);
if(res!='C') break;
}
if(res == '*') printf("玩家赢。 \n");
else if(res == '#') printf("电脑。 \n");
else printf("平局了");
}
// 游戏流程
void test(){
int input = 0;//功能选择输入项
// 随机数
srand((unsigned int)time(NULL));
// 控制游戏的重复
do {
menu();
printf("请选择: ");
scanf( "%d",&input);
switch (input) {
case 1:
printf("\n******** 三 子 棋 ********\n");
game();//游戏内容
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
// 主函数
int main() {
test();
return 0;
}
在此文件中,test()是整体的流程控制。test()中的srand()是因为要使用rand()函数所以提前准备使用的;menu()是进入功能界面的函数;game()是游戏最主要的内容,其内容写在另一个game.c文件中(后面详细解说)。
game.c的头文件game.h
//
// Created by Tian_baby on 2021/12/29.
//
#ifndef ARR_GAME_GAME_H
#define ARR_GAME_GAME_H
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#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 ComputerMove(char board[ROW][COL],int row,int col);
// 判断输赢
char JudgeWin(char board[ROW][COL],int row,int col);
//在game中还有一个函数IsFull()是在game.c中自己使用了所以可以不在这里声明。
#endif //ARR_GAME_GAME_H
该文件主要是对game()中函数使用前的声明。
功能文件game.c
//
// Created by Tian_baby on 2021/12/29.
//
#include "game.h"
// 初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col) {
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) {
for (int i = 0; i < row; i++) {
// 打印一行数据
for (int j = 0; j < col; ++j) {
if (j == col - 1) printf(" %c ", board[i][j]);
else printf(" %c |", board[i][j]);
}
// 打印分隔行
printf("\n");
if (i < row - 1) {
for (int j = 0; j < col; ++j) {
(j < col - 1) ? printf("---|") : printf("---");
}
};
printf("\n");
}
}
// 玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col) {
int x = 0, y = 0;
printf("玩家下棋-->>\n");
printf("请输入你要走的位置:\n");
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("该坐标被占用,请重新输入。\n");
}
} else {
printf("坐标不存在,请重新输入。");
}
}
}
// 电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col) {
int x = 0, y = 0;
printf("电脑下棋-->>\n");
while (1) {
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ') {
board[x][y] = '#';
break;
}
}
}
//判断是否填满 返回一棋盘慢了 返回0棋盘没有满
int IsFull(char board[ROW][COL],int row, int col){
for (int i = 0; i < ROW; ++i) {
for (int j = 0; j < COL; ++j) {
if (board[i][j]==' ') return 0;
}
}
return 1;
}
// 判断输赢
char JudgeWin(char board[ROW][COL], int row, int col) {
// 这个函数返回四种状态--玩家赢"*" 电脑赢"#" 平局"Q" 继续"C"
// 行相等
for (int i = 0; i < row; ++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 < col; ++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[1][1] != ' ')
return board[1][1];
if(board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
return board[1][1];
// same_count = 0;
// for (int i = 0; i < col-1; ++i) {
// if (board[i][i] == board[i+1][i+1]&&board[i][i] != ' ')
// same_count+=1;
// } //-->>这是我自己想的另一种思路 就是判断总次数如果斜线上的所有的值都相等
// 那么same_count的值应该==ROW-1
//是否平局
if(1 == IsFull(board,ROW, COL)) return 'Q';
return 'C';
}
棋盘的初始化InitBoard( ); 打印棋盘DisplayBoard( ); 玩家下棋PlayerMove( ); 电脑下棋ComputerMove( ); 判断输赢JudgeWin()
