目录
前言
相信大家对 “上课好无聊,我们来下棋,我○你×,这盘我先来
” 这样的场景并不陌生,到最后要不就是被老师发现了,要么就是最后还是觉得太无聊了......
可是大学生谁玩这个啊,咱们来点刺激的
(bushi),用代码来造一个能和你玩儿三子棋的 “朋友”,包傻o(╥﹏╥) o!!! 不说了,来正经的~
开干前的思路
在写之前,我们先捋一捋怎么实现它:
一.首先,我们想要实现的功能是,电脑上出现一个棋盘,然后我们下一个,电脑下一个,如果有三个连在一起的,那么就可以直接得出输赢,如果最后满了都没有人赢就是平局,可以再来一局;
二.然后,我们来大致想象一下要怎么一步步实现,先不考虑细节。
1.我们期望可以我想玩就可以一直玩下去,所以可以先用循环打印出一个菜单(好~预定一个函数menu,功能是:→),我输入1,就能开始游戏,输入0,就退出;
2.生成一个二维数组board,然后把数组元素都初始化为‘ ’(如果一个一个赋初值太麻烦了,可以让函数InitBoard来实现);
3.我们要玩肯定要能看见棋盘,所以要把棋盘打印出来,再一想每下一个棋就要打印一次,还是造个PrintBoard函数来得实在;
4.有了棋盘就可以下棋了 ,玩家和电脑一次游戏都要分别下好几次,就可以用两个函数YouPlay和ComputerPlay分别实现玩家落棋和电脑落棋;
5.每次落完棋后就要判断输赢,老样子,来一个函数,就用IsWin吧...
(其实这个代码在IsWin里因为有赢继续和没赢但满了的情况,所以还加了一个IsFull函数判断棋盘是不是满了)
(如果思路足够清晰,细节处理到位,乍一看,还刑啊~(用函数实现功能并将函数声明和定义分模块写更利于检查,理清思路以及合作))
先放一个完整代码![](https://img-blog.csdnimg.cn/c9020dffa9214efc9e6d6d0d1863c711.png)
头文件 game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
//初始化棋盘
void InitBoard(char board[ROW][COL],int row,int col);
//打印棋盘
void PrintBoard(char board[ROW][COL], int row,int col);
//玩家下棋
void YouPlay(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerPlay(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);
//判断棋盘有没有满
int IsFull(char board[ROW][COL], int row, int col);
函数 game.c
#include "game.h"
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//打印棋盘
void PrintBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (j == col - 1)
printf(" %c ", board[i][j]); //最后一列不要|
else
printf(" %c |", board[i][j]);
}
printf("\n");
for (j = 0; j < col; j++)
{
if (i < row - 1)
{
if (j == col - 1) //最后一行不要---|---
printf("---");
else
printf("---|");
}
}
printf("\n");
}
}
//玩家落棋
void YouPlay(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
while (1)
{
printf("请选择落棋的坐标(中间用空格隔开)->:");
scanf("%d %d", &i, &j);
if (i >= 1 && j >= 1 && i <= row && j <= col)
{
if (board[i - 1][j - 1] == ' ')
{
board[i - 1][j - 1] = '*';
PrintBoard(board, row, col);
break;
}
else
{
printf("坐标已被占用,请重新输入!\n");
}
}
else
printf("无效的坐标,请重新输入!\n");
}
}
//电脑落棋
void ComputerPlay(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
while (1)
{
i = rand() % ROW;
j = rand() % COL;
if (board[i][j] == ' ')
{
board[i][j] = '#';
printf("电脑落棋->:\n");
PrintBoard(board, ROW, COL);
break;
}
}
}
//判断输赢
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
for (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];
}
int j = 0;
for (j = 0; j < col; j++) //判断列
{
if (board[0][j] == board[1][j]&& board[1][j] == board[2][j]&& board[0][j] != ' ')
return board[0][j];
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ' || board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ') //判断对角线
return board[1][1];
if (IsFull(board, ROW, COL) == 1)
return 'Q';
return 'C';
}
//判断棋盘是否满了
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
游戏实现 test.c
#include "game.h"
void menu()
{
printf("*************************\n");
printf("******输入1开始游戏******\n");
printf("******输入0退出游戏******\n");
printf("*************************\n");
}
void game()
{
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL); //初始化棋盘
PrintBoard(board, ROW, COL); //打印棋盘
char ret = 0;
while (1)
{
YouPlay(board, ROW, COL); //玩家下棋
ret = IsWin(board, ROW, COL); //判断输赢
if (ret != 'C')
break;
ComputerPlay(board, ROW, COL); //电脑下棋
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
printf("玩家赢了!\n");
if (ret == '#')
printf("电脑赢了!\n");
if (ret == 'Q')
printf("平局!\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu(); //打印菜单提示
printf("请输入->:"); //输入
scanf("%d", &input);
switch (input) //判断
{
case 1:
game(); //游戏入口
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("输入错误,请重新选择!\n");
break;
}
} while (input); //while(1)好像也行
return 0;
}
最后实现的一个效果图,但是不得不说,这个游戏最容易的就是赢电脑(没有优化就是有点像憨憨小孩儿,乱下) ,可能打到平局最难吧
实现效果
内心OS:
不会真的有人看到这里了叭,我要开始叭叭了(历经九九八十一难,主要是给自己长点脑子):
一些思路/错误/知识:
1.一开始是不管三七二十一都要打印菜单的,最后看你输入决定要不要继续玩,do(){}while();就能完美解决。
2.玩家下棋的时候输入的坐标和数组的实际坐标是不一样的,所以落子时的坐标要灵活更改;
3.判断操作符中用于判断相等的是 == 不是 = !!
4.电脑生成的坐标是随机的,所以使用了rand函数,rand函数是[0,100),所以rand()%3就是生成[0,3)的随机数;然后使用要引用头文件#include <stdlib.h>和#include <time.h>然后函数体里加上srand((unsigned int)time(NULL));。
5.最后在判断是否赢的时候要比较数组的3个元素是否相等且不是空格,一定不能写成if(a==b==c!=d),要分开并用&&逻辑操作符连接。
6.IsWin函数需要返回一个值ret,咱就是说直接返回相同元素的元素值比再创造出来一个值更方便。
7.在函数实现的部分,do while循环最后while判断条件也是input,所以input要在do外面创建,不然出了{}之后input的生命周期就结束了。
8.其实直接ROW,COL就可以用3,3代替,但是定义一个需要经常用的常量就可以方便改,可以玩更大棋盘的(但是这里不行,因为判断输赢 的时候只判断了3*3的,怎么说呢,如果不是判断3*3的那更大的棋盘怎么赢,5*5的就要5个相连?改进空间有点大)但是这个思路还是得记录。
9.打印棋盘的时候为了可见及美观,需要加入一些其他的元素,但是边界又不需要,使用循环打印的时候还是要一些变动,可以现在纸上画一下。
10.因为我们在头文件里定义了常量,所以两个.c文件都需要包含“game.h”,而两个文件恰巧都要#include <stdio.h>,所以可以直接只把它写在头文件里。
一般以我来说是几乎不会去认真看别人文字分享出来的代码的,没有思路看到一大堆只会徒增烦恼与熟视无睹,但是我好希望自己能够经常来看看自己记录下来的这些内容和过程,复盘复盘和创新创新,然后坚持!!!谢谢你又来看了一遍,加油@王_哈_哈 JW