如果你也能写出和憨憨电脑玩三子棋(圈叉棋)的代码,那这件事情真的是 泰裤辣 !!!

目录

前言

开干前的思路

完整代码​

头文件 game.h

函数 game.c

游戏实现 test.c

实现效果

一些思路/错误/知识


前言

相信大家对 “上课好无聊,我们来下棋,我○你×,这盘我先来” 这样的场景并不陌生,到最后要不就是被老师发现了,要么就是最后还是觉得太无聊了......

可是大学生谁玩这个啊,咱们来点刺激的(bushi),用代码来造一个能和你玩儿三子棋的 “朋友”,包傻o(╥﹏╥) o!!!    不说了,来正经的~


 开干前的思路

在写之前,我们先捋一捋怎么实现它:

一.首先,我们想要实现的功能是,电脑上出现一个棋盘,然后我们下一个,电脑下一个,如果有三个连在一起的,那么就可以直接得出输赢,如果最后满了都没有人赢就是平局,可以再来一局;

二.然后,我们来大致想象一下要怎么一步步实现,先不考虑细节。

1.我们期望可以我想玩就可以一直玩下去,所以可以先用循环打印出一个菜单(好~预定一个函数menu,功能是:→),我输入1,就能开始游戏,输入0,就退出

2.生成一个二维数组board,然后把数组元素都初始化为‘ ’(如果一个一个赋初值太麻烦了,可以让函数InitBoard来实现);

3.我们要玩肯定要能看见棋盘,所以要把棋盘打印出来,再一想每下一个棋就要打印一次,还是造个PrintBoard函数来得实在;

4.有了棋盘就可以下棋了 ,玩家和电脑一次游戏都要分别下好几次,就可以用两个函数YouPlayComputerPlay分别实现玩家落棋电脑落棋

5.每次落完棋后就要判断输赢,老样子,来一个函数,就用IsWin吧...

(其实这个代码在IsWin里因为有赢继续和没赢但满了的情况,所以还加了一个IsFull函数判断棋盘是不是满了

(如果思路足够清晰,细节处理到位,乍一看,还刑啊~(用函数实现功能并将函数声明和定义分模块写更利于检查,理清思路以及合作))

先放一个完整代码

头文件 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

  • 15
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王_哈_哈 Jw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值