五子棋技巧没子了能不能顺着对角线移动?

查看: 1716|回复: 8
19X19五子棋对角线公式怎么写(原来offset(offset())也可以用!)
阅读权限95
在线时间 小时
本帖最后由 sharprain 于
08:36 编辑
数组公式.png (18.41 KB, 下载次数: 2)
21:37 上传
题目如图所示,横竖的公式我会写,对角线却遇到了麻烦,哪位高人有办法,请帮忙。
(11.41 KB, 下载次数: 18)
21:37 上传
点击文件名下载附件
阅读权限95
在线时间 小时
本帖最后由 sharprain 于
08:44 编辑
wddn 发表于
19X19五子棋对角线公式怎么写
憋了一早上,终于憋出来了,差点搞出内伤,呵呵,
参考了吴姐的竞赛题:
offset(offset())原来这样也可以呵呵
向下对角线的公式是:=OR(MMULT(N(OFFSET(OFFSET(A1,COLUMN(A:E)-1,COLUMN(A:E)-1),MOD(ROW(1:225)-1,15),INT((ROW(1:225)-1)/15))),ROW(1:5)^0)=5)复制代码=OR(MMULT(N(OFFSET(OFFSET(A1,COLUMN(A:E)-1,5-COLUMN(A:E)),MOD(ROW(1:225)-1,15),INT((ROW(1:225)-1)/15))),ROW(1:5)^0)=5)复制代码版主看看可否
阅读权限95
在线时间 小时
5子棋有许多不同的规则:
有三三连为负的,有长连星也为负的,
这就要判定刚下的子是否是造成 3 3 连的。
阅读权限95
在线时间 小时
本帖最后由 sharprain 于
19:10 编辑
wddn 发表于
19X19五子棋对角线公式怎么写
版主的公式很帅,可以有没有通用公式,如果连续6个,7个呢,有没有更好的办法
阅读权限95
在线时间 小时
delete_007 发表于
向下的对角线。
请考虑五子棋的规则,不是单独指在对角线上的,所谓的向下的对角线应该说是,行加列相等的单元格,比如
A5,B4,C3,D2,E1应该算是在对角线上;
而向上的对角线是说,行号=列号数;比如S15,R16,Q17,P18,O19应该也算是对角线;
对不起,没有说清楚
阅读权限95
在线时间 小时
本帖最后由 丢丢表格 于
23:27 编辑
用VBA 写相对简单
只要对焦点单元格位的正负4 , 9*9&&范围进行计算是否有5连就行
这个东东以前我写过,不过现在用WPS 了。用不上 VBA 了
阅读权限100
在线时间 小时
& & & & & & & &
19X19五子棋对角线公式怎么写
23:23 上传
点击文件名下载附件
3.53 KB, 下载次数: 23
阅读权限100
在线时间 小时
& & & & & & & &
向上的对角线可以在OFFSET上做文章。
阅读权限100
在线时间 小时
=MAX(FREQUENCY(IF(N(OFFSET(A1,ROW(1:19)-1,ROW(1:19)-1)),ROW(1:19)),IF(N(OFFSET(A1,ROW(1:19)-1,ROW(1:19)-1))=0,ROW(1:19))))&4复制代码向下的对角线。
您需要登录后才可以回帖
玩命加载中,请稍候
玩命加载中,请稍候
Powered by
本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任! & & 本站特聘法律顾问:徐怀玉律师 李志群律师第二课时&&五子棋的棋具
第二课&&五子棋的棋具
&同学们,大多数人都认为自己会下五子棋,其实他们中很多人会下的五子棋跟我们要学习的五子棋是有区别的,区别在什么地方呢,你们通过学习就明白了。我们先来认识五子棋的棋具吧,棋具包括棋盘和棋子。
&&&&让我们首先来认识棋盘,五子棋的棋盘横竖都是十五条线,如果你认为棋盘之中的每一个小方格都是正方形,那你就错了!其实棋盘的横向稍微窄一点,竖向稍微宽一点,每个方格都是近似正方形的长方形。横向从左到右用a到o共十五个英语字母标出,竖向从下到上用1到15共十五个阿拉伯数字标出。棋盘上的横线和竖线共交叉形成了225个交叉点,棋子就落在棋盘的这些交叉点上。每个交叉点都有它位置的坐标,来说明它在棋盘上的准确位置,这些坐标由英语字母在前、阿拉伯数字在后组合而成,如:C5、J13、A15、O1、I7等。你能在棋盘上指出这些点的具体位置吗?或者别人随便指出棋盘上的任意几点,你就马上说出这些点的坐标吗?如果不熟练的话,希望你好好练习呦。
&&&&棋盘上有5个比较特殊的交叉点,用小黑点标识出来,叫做星;中间的星叫天元(坐标是H8),表示棋盘的正中心; 四周的4个星叫小星(坐标分别是D12、L12、D4、L4),表示棋盘的四个角落;星在棋盘上起一定的标示位置作用。棋盘上看得见的横竖线叫做阳线,交叉点之间、看不见的、与棋盘对角线平行的斜线叫做阴线。
&&&&下面我们再来认识棋子,棋子由黑白两种颜色组成。五子棋由两个人下,一人拿黑棋,另一个人拿白棋,黑棋先走,白棋后走。共有225个棋子,与交叉点的个数相同;其中黑棋113个,白棋112个,不过平时下棋棋子少些也是可以的。正确的拿棋子的方法是食指的指甲与中指的指肚儿夹住棋子。棋子落在棋盘的交叉点上,落下后不能移动,也不能吃子。课内练习:
1、五子棋的棋具包括什么?
2、什么叫阳线?什么叫阴线?
3、棋盘上有几个星?中央的星叫天元,四周的星的名字呢?
4、C11、J2、F9、M14、O15你能在棋盘上指出来吗?棋盘上任意指出五个点你能很快说出它们的坐标吗?
5、五子棋拿棋子的正确方法是什么?
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。Android实训案例(八)――单机五子棋游戏,自定义棋盘,线条,棋子,游戏逻辑,游戏状态存储,再来一局
阿法狗让围棋突然就被热议了,鸿洋大神也顺势出了篇五子棋单机游戏的视频,我看到了就像膜拜膜拜,就学习了一下,写篇博客梳理一下自己的思路,加深一下印象
视频链接:
我们一看就知道,我们必须自定义View,这里我们定义一个GameView来做游戏主类,第一步,先测量,我们这里不难知道,五子棋他的棋盘是一个正方形,所以我们需要去测量
* @param widthMeasureSpec
* @param heightMeasureSpec
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取高宽值
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int hightSize = MeasureSpec.getSize(heightMeasureSpec);
int hightMode = MeasureSpec.getMode(heightMeasureSpec);
//拿到宽和高的最小值,也就是宽
int width = Math.min(widthSize, heightMeasureSpec);
//根据测量模式细节处理
if (widthMode == MeasureSpec.UNSPECIFIED) {
width = hightS
} else if (hightMode == MeasureSpec.UNSPECIFIED) {
width = widthS
//设置这样就是一个正方形了
setMeasuredDimension(width, width);
这里的逻辑还是十分简单的,我们拿到长和宽去比较一下,设置这个View的长宽Wie最小值,就是一个正方形了,所以我们的layout_main.xml是这样写的
&linearlayout xmlns:android=&/apk/res/android& xmlns:tools=&/tools& android:layout_width=&match_parent& android:layout_height=&match_parent& android:orientation=&vertical& android:background=&@drawable/main_bg&&
&com.lgl.fiverow.gameview android:layout_width=&match_parent& android:layout_height=&match_parent&&
&/com.lgl.fiverow.gameview&&/linearlayout&
这里我在构造方法中设置了一个半透明的红色背景,是在我们调试的时候可以更加清晰的看清楚GameView的大小,所以,运行的结果
这个应该也算是棋盘的一部分吧,就是棋盘上的线条,我们应该怎么去画,首先,我们要去定义一些属性
//线条数量
private static final int MAX_LINE = 10;
//线条的宽度
private int mPanelW
//线条的高度
private float mLineH
然后,我们要去确定大小
* 测量大小
* @param w
* @param h
* @param oldw
* @param oldh
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mPanelWidth =
mLineHeight = mPanelWidth * 1.0f / MAX_LINE;
不要着急,这些都只是一些准备的工作,我们画线条是必须要在onDraw(0方法里的,但是前期我们要准备一只画笔,对吧,所以我们要初始化画笔
* 初始化画笔
private void initPaint() {
//设置颜色
mPaint.setColor(0x);
mPaint.setAntiAlias(true);
//设置防抖动
mPaint.setDither(true);
//设置Style
mPaint.setStyle(Paint.Style.STROKE);
现在我们可以去绘制了,我们在OnDraw(0方法里写一个drawLine方法来专门绘制线条
* 绘制棋盘的方法
* @param canvas
private void drawLine(Canvas canvas) {
//获取高宽
int w = mPanelW
float lineHeight = mLineH
//遍历,绘制线条
for (int i = 0; i & MAX_LINE; i++) {
int startX = (int) (lineHeight / 2);
int endX = (int) (w - lineHeight / 2);
int y = (int) ((0.5 + i) * lineHeight);
canvas.drawLine(startX, y, endX, y, mPaint);
canvas.drawLine(y, startX, y, endX, mPaint);
我们运行一下
好的,这里,注意一下,我在activity_main.xml中定义了一个
android:gravity=&center&
属性,所以让他居中,同样的,我们在initPaint中加上点代码让我们看的更加直观一点
//设置颜色
mPaint.setColor(Color.BLACK);
//设置线条宽度
mPaint.setStrokeWidth(3);
同样的,我们把构造法里的设置背景的测试代码注释掉
//测试代码
//setBackgroundColor(0x44ff0000);
这样,我们运行一下
得,我们现在有模有样了
棋子我们事先准备好了两张图片,但是这里我们要考虑他的大小的问题了,我们的思路是让他是行高的四分之三大小,所以先声明
private Bitmap mB
private Bitmap mW
//比例,棋子的大小是高的四分之三
private float rowSize = 3 * 1.0f / 4;
然后我们定义一个方法区初始化Bitmap
* 初始化棋子
private void initBitmap() {
//拿到图片资源
mBlack = BitmapFactory.decodeResource(getResources(), R.drawable.stone_black);
mWhite = BitmapFactory.decodeResource(getResources(), R.drawable.stone_white);
拿到资源之后我们就可以设置大小了,我们在onSizeChanged()里面设置
//棋子宽度
int mWhiteWidth = (int) (mLineHeight * rowSize);
//修改棋子大小
mWhite = Bitmap.createScaledBitmap(mWhite, mWhiteWidth, mWhiteWidth, false);
mBlack = Bitmap.createScaledBitmap(mBlack, mWhiteWidth, mWhiteWidth, false);
不过棋子可没我们想象的那么简单,我们要点击一下再去绘制一个棋子,这样的思路该怎么去实现呢?我们实现它的点击事件,这里先定义几个变量
//存储用户点击的坐标
private List mWhiteArray = new ArrayList&&();
private List mBlackArray = new ArrayList&&();
//标记,是执黑子还是白子 ,白棋先手
private boolean mIsWhite =
这样才和触摸事件相得映彰
* 触摸事件
* @param event
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
//按下事件
case MotionEvent.ACTION_UP:
int x = (int) event.getX();
int y = (int) event.getY();
//封装成一个Point
Point p = getValidPoint(x, y);
//判断当前这个点是否有棋子了
if(mWhiteArray.contains(p) || mBlackArray.contains(p)){
//点击不生效
//判断如果是白子就存白棋集合,反之则黑棋集合
if (mIsWhite) {
mWhiteArray.add(p);
mBlackArray.add(p);
invalidate();
mIsWhite = !mIsW
这样,有几点是要说明一下的,首先我们new Point的时候为了避免重复绘制我们是实现了一个方法
* 不能重复点击
* @param x
* @param y
private Point getValidPoint(int x, int y) {
return new Point((int) (x / mLineHeight), (int) (y / mLineHeight));
紧接着我们就判断,要是重复点击,返回false,而且我们在action选择也是选择了ACTION_UP,为什么?为什么不是ACTION_DOWN?因为这个毕竟是一个View,父View会拦截(某些场景),所以我们选在UP上才是合情合理的
好的,当我们点击之后就要绘制棋子了,这里我们也写一个方法
* 绘制棋子的方法
* @param canvas
private void drawPieces(Canvas canvas) {
for (int i = 0; i & mWhiteArray.size(); i++) {
//获取白棋子的坐标
Point whitePoint = mWhiteArray.get(i);
canvas.drawBitmap(mBlack, (whitePoint.x + (1 - rowSize) / 2) * mLineHeight, (whitePoint.y + (1 - rowSize) / 2) * mLineHeight, null);
for (int i = 0; i & mBlackArray.size(); i++) {
//获取黑棋子的坐标
Point blackPoint = mBlackArray.get(i);
canvas.drawBitmap(mWhite, (blackPoint.x + (1 - rowSize) / 2) * mLineHeight, (blackPoint.y + (1 - rowSize) / 2) * mLineHeight, null);
OK,我们实际运行一下
四.游戏逻辑
现在什么都有了,基本上都可用玩了,但是还少了重要的一点就是游戏结束,你到了五颗也需要判断是否胜利呀,对吧,我们写一个方法,在每次绘制完成之后就去判断是否有赢家
* 判断是否胜利
private void checkWin() {
//判断白棋是否有五个相同的棋子相连
boolean mWhiteWin = checkFiveLine(mWhiteArray);
//判断黑棋是否有五个相同的棋子相连
boolean mBlackWin = checkFiveLine(mBlackArray);
//只要有一个胜利,游戏就结束
if (mWhiteWin || mBlackWin) {
mIsGameOver =
mIsWhiteWin = mWhiteW
Toast.makeText(getContext(), mIsWhiteWin ? &白棋胜利& : &黑棋胜利&, Toast.LENGTH_SHORT).show();
好的,我们重点逻辑就在checkFiveLine这个方法上了,这里,我们所知道的胜利有四种情况
我们先定义一个常量
//胜利棋子数量
private static final int MAX_COUNT_IN_LINE = 5;
OK,接下来我们可以实现以下胜利的逻辑了
* //判断棋子是否有五个相同的棋子相连
* @param points
private boolean checkFiveLine(List points) {
//遍历棋子
for (Point p : points) {
//拿到棋盘上的位置
int x = p.x;
int y = p.y;
* 四种情况胜利,横,竖,左斜,右斜
boolean win = checkHorizontal(x, y, points);
win = checkVertical(x, y, points);
win = checkLeft(x, y, points);
win = checkRight(x, y, points);
我们不管哪个方向只要返回true就返回true,然后弹Toast,这里,四个方向的逻辑
* 判断横向的棋子
* @param x
* @param y
* @param points
private boolean checkHorizontal(int x, int y, List points) {
//棋子标记,记录是否有五个
=1是因为自身是一个
int count = 1;
for (int i = 1; i & MAX_COUNT_IN_LINE; i++) {
if (points.contains(new Point(x - i, y))) {
//有五个就为true
if (count == MAX_COUNT_IN_LINE) {
for (int i = 1; i & MAX_COUNT_IN_LINE; i++) {
if (points.contains(new Point(x + i, y))) {
//有五个就为true
if (count == MAX_COUNT_IN_LINE) {
* 判断纵向的棋子
* @param x
* @param y
* @param points
private boolean checkVertical(int x, int y, List points) {
//棋子标记,记录是否有五个
=1是因为自身是一个
int count = 1;
for (int i = 1; i & MAX_COUNT_IN_LINE; i++) {
if (points.contains(new Point(x, y - i))) {
//有五个就为true
if (count == MAX_COUNT_IN_LINE) {
for (int i = 1; i & MAX_COUNT_IN_LINE; i++) {
if (points.contains(new Point(x, y + i))) {
//有五个就为true
if (count == MAX_COUNT_IN_LINE) {
* 判断左斜向的棋子
* @param x
* @param y
* @param points
private boolean checkLeft(int x, int y, List points) {
//棋子标记,记录是否有五个
=1是因为自身是一个
int count = 1;
for (int i = 1; i & MAX_COUNT_IN_LINE; i++) {
if (points.contains(new Point(x - i, y + i))) {
//有五个就为true
if (count == MAX_COUNT_IN_LINE) {
for (int i = 1; i & MAX_COUNT_IN_LINE; i++) {
if (points.contains(new Point(x + i, y - i))) {
//有五个就为true
if (count == MAX_COUNT_IN_LINE) {
* 判断右斜向的棋子
* @param x
* @param y
* @param points
private boolean checkRight(int x, int y, List points) {
//棋子标记,记录是否有五个
=1是因为自身是一个
int count = 1;
for (int i = 1; i & MAX_COUNT_IN_LINE; i++) {
if (points.contains(new Point(x - i, y - i))) {
//有五个就为true
if (count == MAX_COUNT_IN_LINE) {
for (int i = 1; i & MAX_COUNT_IN_LINE; i++) {
if (points.contains(new Point(x + i, y + i))) {
//有五个就为true
if (count == MAX_COUNT_IN_LINE) {
这样,我们运行一下
嘿嘿,好玩吧!
五.游戏状态存储
这个就是当我们游戏挂后台之后,再回来游戏就没了,我们应该存储他的状态,让他每一次进入的时候要是上一句没有下完接着下,那我们该怎么去实现呢?和Activity一样,我们View也有存储状态的方法
* 存储状态
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
bundle.putParcelable(INSTANCE, super.onSaveInstanceState());
bundle.putBoolean(INSTANCE_GAMEOVER, mIsGameOver);
bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY, mWhiteArray);
bundle.putParcelableArrayList(INSTANCE_BLACK_ARRAY, mBlackArray);
* 重新运行
* @param state
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle)
mIsGameOver = bundle.getBoolean(INSTANCE_GAMEOVER);
mWhiteArray = bundle.getParcelableArrayList(INSTANCE_WHITE_ARRAY);
mBlackArray = bundle.getParcelableArrayList(INSTANCE_BLACK_ARRAY);
super.onRestoreInstanceState(bundle.getParcelable(INSTANCE));
super.onRestoreInstanceState(state);
这样就可以了,但是,有一点要知道,不要忘记在布局文件上给控件加上ID,不然状态不会存储哦
六.再来一局
既然我们的游戏逻辑差不多了,那我们应该考虑一下当你胜利的时候,你是不是应该再来一局,所以我们还要实现这个逻辑,这个很简单
* 再来一局
public void RestartGame() {
mWhiteArray.clear();
mBlackArray.clear();
mIsGameOver =
mIsWhiteWin =
invalidate();
这样,我们就可以直接调用了,我们来看看MainActivity
package com.lgl.
import android.support.design.widget.FloatingActionB
import android.support.v7.app.AppCompatA
import android.os.B
import android.view.V
* 五子棋游戏
public class MainActivity extends AppCompatActivity {
//重来按钮
private FloatingActionB
private GameV
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
game = (GameView) findViewById(R.id.mGameView);
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
game.RestartGame();
OK,我们最终运行一下
OK,到这里,就算开发完成了
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'基于C语言实现五子棋游戏完整实例代码-android100学习网
基于C语言实现五子棋游戏完整实例代码
本文实例讲述了基于C语言实现五子棋游戏的方法,代码备有比较完整的注释,可以帮助读者更好的加以理解。 五子棋游戏代码如下:
* 使用键盘的上下左右键移动棋盘,空格键表示下棋,ESC键退出
本文实例讲述了基于C语言实现五子棋游戏的方法,代码备有比较完整的注释,可以帮助读者更好的加以理解。
五子棋游戏代码如下:
* 使用键盘的上下左右键移动棋盘,空格键表示下棋,ESC键退出程序
#include &stdio.h&
#include &stdlib.h&
#include &bios.h&
#include &graphics.h&
#include&malloc.h&
* 对应键盘键的十六进制数字
#define ESC 0x11b
#define UP 0x4800
#define DOWN 0x5000
#define LEFT 0x4b00
#define RIGHT 0x4d00
#define BLANK 0x3920
#define PLAYER1 1
#define PLAYER2 2
#define COMPUTER 2
#define LENGTH 15
#define SEARCH_DEEP 2
* 用来在函数can_expand()查找可以扩展的节点步长
#define STEP 1
/************全局变量定义***************/
oldx = 240,
oldy = 240;
step_sum = 0;
chessman[LENGTH][LENGTH];
depth = 2; /* 搜索的深度 */
win_flag = 0;
typedef struct five_chess *
struct five_chess {
chess[LENGTH][LENGTH];
record[LENGTH][LENGTH];
stack_deep0 = 0;
stack_c[10];
close[600];
push(point s0)
if (stack_deep0 & 10)
stack_c[stack_deep0++] = s0;
if (stack_deep0 & 0)
return stack_c[stack_deep0 - 1];
/*else return 一个什么样的东西?*/
if (stack_deep0 & 0)
stack_deep0--;
is_empty()
if (stack_deep0 != 0)
/************函数的声明**************/
win_or_not(int x0, int y0, int who,
int chessman[LENGTH][LENGTH], int a);
set_chessman();
print_result();
/************评价函数部分************/
score_row(int i, int j, int chessman[LENGTH][LENGTH]);
score_col(int i, int j, int chessman[LENGTH][LENGTH]);
score_diag_45(int i, int j, int chessman[LENGTH][LENGTH]);
score_diag_135(int i, int j, int chessman[LENGTH][LENGTH]);
total_score(int who_running, int chessman[LENGTH][LENGTH]);
score(int chessman[LENGTH][LENGTH]);
rowdt(int i, int j, int chessman[LENGTH][LENGTH]);
coldt(int i, int j, int chessman[LENGTH][LENGTH]);
diadt(int i, int j, int chessman[LENGTH][LENGTH]);
vdiadt(int i, int j, int chessman[LENGTH][LENGTH]);
can_expand(int i, int j, int chessman[LENGTH][LENGTH]);
copy(point s1, point s0);
POW(int s, int t)
if (t &= 0)
for (i = 0; i & i++)
* 定义computer先手
expand(point s0)
new_chess = (point) malloc(sizeof(struct five_chess));
/*************************这里出错***********************************/
for (i = 0; i & LENGTH; i++)
for (j = 0; j & LENGTH; j++)
new_chess-&chess[i][j] = s0-&chess[i][j];
for (i = 0; i & LENGTH; i++)
for (j = 0; j & LENGTH; j++)
new_chess-&record[i][j] = s0-&chess[i][j];
/*************************这里出错***********************************/
if (s0-&layer % 2 == 0)
flag = COMPUTER;
flag = PLAYER1;
for (i = 0; i & LENGTH; i++)
for (j = 0; j & LENGTH; j++) {
if (s0-&record[i][j])
/*如果有棋子*/
if (can_expand(i, j, s0-&chess) == 0)
/*如果有棋子,而且沿水平,树直,左上—右下,右上—左下,四个方向可以扩展*/
s0-&record[i][j] =
new_chess-&chess[i][j] =
new_chess-&layer = s0-&layer + 1;
new_chess-&x =
new_chess-&y =
new_chess-&record[i][j] =
return new_
* for(i=5;i&10;i++) for(j=5;j&10;j++){ if(s0-&record[i][j])
* if(can_expand(i,j,s0-&chess)==0) s0-&record[i][j]=
* new_chess-&x=i; new_chess-&y=j; new_chess-&record[i][j]=
* new_chess-&layer=s0-&layer+1; new_chess-&chess[i][j]= return
* new_ } for(i=2;i&12;i++) for(j=2;j&12;j++){
* if(i&4&&i&10&&j&4&&j&10) if(s0-&record[i][j])
* if(can_expand(i,j,s0-&chess)==0) s0-&record[i][j]=
* new_chess-&x=i; new_chess-&y=j; new_chess-&record[i][j]=
* new_chess-&layer=s0-&layer+1; new_chess-&chess[i][j]= return
* } for(i=0;i&LENGTH;i++) for(j=0;j&LENGTH;j++){
* if(i&1&&i&12&&j&1&&j&12) if(s0-&record[i][j])
* if(can_expand(i,j,s0-&chess)==0) s0-&record[i][j]=
* new_chess-&chess[i][j]= new_chess-&layer=s0-&layer+1;
* new_chess-&x=i; new_chess-&y=j; new_chess-&record[i][j]= return
new_chess-&layer = -1;
return new_
computer()
break_now = 0;
break_then = 0;
go_on = 0;
s0 = NULL,
s1 = NULL,
s2 = NULL,
max_chess = NULL;
temps = NULL,
* 堆栈的初始化
stack_deep0 = 0;
s0 = malloc(sizeof(struct five_chess));
for (i = 0; i & 600; i++)
/*为什么是600*/
close[i] = NULL;
/*close是一个point 数组*/
close[num++] = s0;
for (i = 0; i & LENGTH; i++)
for (j = 0; j & LENGTH; j++) {
s0-&chess[i][j] = chessman[i][j];
s0-&record[i][j] = chessman[i][j];
s0-&layer = 0;
s0-&value = -3000000;
s0-&score = -3000000;
while (is_empty() != 0) {
/*看是栈否为空*/
s01 = top();
/*如果不是空*/
s1 = expand(s01);
/*从栈顶开始展开*/
close[num++] = s1;
if (s1-&layer == -1) {
win_or_not((s1-&x + 1) * 30, (s1-&y + 1) * 30, 2, s1-&chess,
if (go_on == 2) {
a = (s1-&x + 1) * 30;
b = (s1-&y + 1) * 30;
break_then = 1;
win_or_not((s1-&x + 1) * 30, (s1-&y + 1) * 30, 1, s1-&chess,
if (go_on == 1) {
a = (s1-&x + 1) * 30;
b = (s1-&y + 1) * 30;
break_then = 1;
s1-&value = 30000;
while (1) {
s1 = top();
s2 = expand(s1);
if (s2-&layer == -1) {
if (s1-&value & top()-&value) {
top()-&value = s1-&
max_chess = s1;
}/*end of if*/
s2-&score = score(s2-&chess);
temps = top();
if (s2-&score & temps-&value)
temps-&value = s2-&
}/*end of whiile(1) */
if (break_then == 0) {
for (i = 0; i & LENGTH; i++) {
for (j = 0; j & LENGTH; j++)
if (max_chess-&chess[i][j] != chessman[i][j]) {
a = i * 30 + 30;
b = j * 30 + 30;
break_now = 1;
if (break_now == 1)
for (i = 0; i & 600; i++) {
if (close[i] == NULL)
free(close[i]);
/**********************************************************/
play_with_who = 1;
printf("1.Play with human\n2.Play with computer\nPlease choice: ");
scanf("%d", &play_with_who);
/*显示棋盘*/
if (play_with_who == 1) {
/*人与人玩*/
while (1) {
/*设置人与人玩的界面*/
settextstyle(0, 0, 2);
if ((step_sum + 1) % 2) {
setcolor(1);
outtextxy(500, 180, "Player2");
setcolor(4);
outtextxy(500, 180, "Player1");
setcolor(1);
outtextxy(500, 180, "Player1");
setcolor(10);
outtextxy(500, 180, "Player2");
if (bioskey(1))
* 按了一次键盘那么就true,执行下面代码,这是bios。h
key = bioskey(0);
* 返回一个键盘值,如没有按键,则一直等待
switch (key) {
case LEFT:
if (x1 & 30) {
/*显示方框*/
if (y1 & 30) {
case RIGHT:
if (x1 & 450) {
case DOWN:
if (y1 & 450) {
case BLANK:
/*按下空格键后放置棋子*/
if (chessman[x1 / 30][y1 / 30])
/*如果当前位置有棋子,不能放置,退出*/
step_sum++;
/*如果没有棋子,下一步谁走加1*/
* P1 设置棋子
if (step_sum % 2) {
setcolor(15);
/*画棋子*/
setfillstyle(SOLID_FILL, 15); /* 封闭图形,进行实体填充*/
circle(x1, y1, 10);
floodfill(x1, y1, 15);
/*填充圆*/
chessman[x1 / 30][y1 / 30] = PLAYER1;
/*设置棋盘状态*/
win_flag = win_or_not(x1, y1, 1, chessman, 0);
/*分析游戏是否结束,谁胜谁败*/
if (win_flag == 1)
outtextxy(480, 240, "P1 Win");
else if (win_flag == 3)
outtextxy(480, 240, "DOGFALL");
if (win_flag != 0) {
/*如果没人胜,游戏继续*/
while (bioskey(1) == 0);
closegraph();
/*what this mean?*/
} else { /* P2 设置棋子 */
setcolor(12);
setfillstyle(SOLID_FILL, 12);
circle(x1, y1, 10);
floodfill(x1, y1, 12);
chessman[x1 / 30][y1 / 30] = PLAYER2;
win_flag = win_or_not(x1, y1, 2, chessman, 0);
if (win_flag == 2)
outtextxy(480, 240, "P2 Win");
else if (win_flag == 3)
outtextxy(480, 240, "DOGFALL");
if (win_flag != 0) {
while (bioskey(1) == 0);
closegraph();
chessman[7][7] = COMPUTER;
/*人和电脑玩,电脑先走一步*/
setcolor(12);
setfillstyle(SOLID_FILL, 12);
circle(240, 240, 10);
floodfill(240, 240, 12);
flag_run = 0;
/*有什么用?*/
step_sum++;
/*下一步谁走?*/
while (1) {
while (1) {
if (flag_run == 1)
if (bioskey(1)) {
key = bioskey(0);
* 返回一个键盘值,如没有按键,则一直等待
switch (key) {
case LEFT:
if (x1 & 30) {
if (y1 & 30) {
case RIGHT:
if (x1 & 450) {
case DOWN:
if (y1 & 450) {
case BLANK:
if (chessman[x1 / 30 - 1][y1 / 30 - 1])
/*有棋子了不走*/
setcolor(15);
setfillstyle(SOLID_FILL, 15); /* 封闭图形,进行实体填充
circle(x1, y1, 10);
floodfill(x1, y1, 15);
/*画棋子*/
chessman[x1 / 30 - 1][y1 / 30 - 1] = PLAYER1;
flag_run = 1;
/*有什么用?*/
step_sum++;
/*下一步谁走*/
win_flag = win_or_not(x1, y1, 1, chessman, 0);
/*谁胜谁负*/
if (win_flag == 1)
outtextxy(480, 240, "P1 Win");
else if (win_flag == 3)
outtextxy(480, 240, "DOGFALL");
if (win_flag != 0) {
while (bioskey(1) == 0);
/*没有人胜则继续等待下棋*/
closegraph();
} /* switch */
computer();
/*调用智能体*/
* a,b存放的是现在电脑准备下的位置
* 返回一个a,b的结构体不是更好,用全局变量不爽啊
* struct {
setcolor(12);
setfillstyle(SOLID_FILL, 12);
circle(a, b, 10);
floodfill(a, b, 12);
chessman[a / 30 - 1][b / 30 - 1] = COMPUTER;
flag_run = 0;
step_sum++;
win_flag = win_or_not(a, b, 2, chessman, 0);
if (win_flag == 2)
outtextxy(480, 240, "ComputerWin");
else if (win_flag == 3)
outtextxy(480, 240, "DOGFALL");
if (win_flag != 0) {
while (bioskey(1) == 0);
closegraph();
* 画棋盘的过程
gdriver = DETECT,
registerbgidriver(EGAVGA_driver);
initgraph(&gdriver, &gmode, " ");
* 对显示适配器进行配置
setbkcolor(1);
for (i = 0; i & 30; i++) {
setcolor((i &= 2) ? 9 : i);
rectangle(i, i, 479 - i, 479 - i); /* 画矩形边框 */
for (i = 1; i & 14; i++)
for (j = 1; j & 14; j++) {
setcolor(14);
line(30 + 30 * i, 30, 30 + 30 * i, 449);
line(30, 30 + 30 * i, 449, 30 + 30 * i);
* 画整个图的边框
for (i = 0; i & 15; i++) {
setcolor(i);
rectangle(i, i, 640 - i, 480 - i);
line(480 - i, 15, 480 - i, 465);
* 输出屏幕右侧的信息
setcolor(4);
settextstyle(0, 0, 2);
outtextxy(500, 45, "GOBANG");
setcolor(10);
settextstyle(0, 0, 1);
outtextxy(500, 90, "Designed By");
outtextxy(514, 118, "Ye Binbin");
outtextxy(480, 140, "from class A of CS");
* 移动光标
setcolor(1);
if (oldx & 450) {
if (oldy & 30)
line(oldx + 7, oldy - 15, oldx + 15, oldy - 15);
if (oldy & 30)
line(oldx + 15, oldy - 15, oldx + 15, oldy - 7);
if (oldy & 450)
line(oldx + 15, oldy + 7, oldx + 15, oldy + 15);
if (oldy & 450)
line(oldx + 15, oldy + 15, oldx + 7, oldy + 15);
if (oldx & 30) {
if (oldy & 450)
line(oldx - 7, oldy + 15, oldx - 15, oldy + 15);
if (oldy & 450)
line(oldx - 15, oldy + 15, oldx - 15, oldy + 7);
if (oldy & 30)
line(oldx - 15, oldy - 7, oldx - 15, oldy - 15);
if (oldy & 30)
line(oldx - 15, oldy - 15, oldx - 7, oldy - 15);
setcolor(12);
if (x1 & 450) {
if (y1 & 30)
line(x1 + 7, y1 - 15, x1 + 15, y1 - 15);
if (y1 & 30)
line(x1 + 15, y1 - 15, x1 + 15, y1 - 7);
if (y1 & 450)
line(x1 + 15, y1 + 7, x1 + 15, y1 + 15);
if (y1 & 450)
line(x1 + 15, y1 + 15, x1 + 7, y1 + 15);
if (x1 & 30) {
if (y1 & 450)
line(x1 - 7, y1 + 15, x1 - 15, y1 + 15);
if (y1 & 450)
line(x1 - 15, y1 + 15, x1 - 15, y1 + 7);
if (y1 & 30)
line(x1 - 15, y1 - 7, x1 - 15, y1 - 15);
if (y1 & 30)
line(x1 - 15, y1 - 15, x1 - 7, y1 - 15);
oldx = x1;
oldy = y1;
set_chessman()
* 棋子有三种状态,0是未初始状态,1是控制方棋子,2是对方棋子
for (i = 0; i & 15; i++)
for (j = 0; j & 15; j++)
chessman[i][j] = 0;
* 0表示没有赢,1表示p1胜利,2表示p2胜利,3表示平局
win_or_not(int x0, int y0, int who, int chessman[LENGTH][LENGTH], int a)
i = x0 / 30 - 1,
j = y0 / 30 - 1;
line_sum = -1;
tmp_i = i,
if (a == 1) {
* 测试第一层扩展是否满足赢的条件
c = chessman[i][j];
chessman[i][j] = who_
while (1) {
/* 查找共行的棋子是否连接了五个 */
while (tmp_i &= 0 && line_sum != 4) {
if (chessman[tmp_i--][j] == who_run)
line_sum++;
if (line_sum == 4)
line_sum++;
while (tmp_i &= 15 && line_sum != 5) {
if (chessman[tmp_i++][j] == who_run)
line_sum++;
if (line_sum == 5) {
if (a == 1)
chessman[i][j] =
return who_
line_sum = -1;
while (1) {
/* 查找共列的棋子是否连接了五个 */
while (tmp_j &= 0 && line_sum != 4) {
if (chessman[i][tmp_j--] == who_run)
line_sum++;
if (line_sum == 4)
line_sum++;
while (tmp_j &= 15 && line_sum != 5) {
if (chessman[i][tmp_j++] == who_run)
line_sum++;
if (line_sum == 5) {
if (a == 1)
chessman[i][j] =
return who_
line_sum = -1;
while (1) {
/* 查找上对角线上是否连接了五个 */
while (line_sum != 4 && tmp_i &= 15 && tmp_j &= 0) {
if (chessman[tmp_i++][tmp_j--] == who_run)
line_sum++;
if (line_sum == 4)
line_sum++;
while (line_sum != 5 && tmp_i &= 0 && tmp_j &= 15) {
if (chessman[tmp_i--][tmp_j++] == who_run)
line_sum++;
if (line_sum == 5) {
if (a == 1)
chessman[i][j] =
return who_
line_sum = -1;
while (1) {
/* 查找下对角线上是否连接了五个 */
while (line_sum != 4 && tmp_i &= 0 && tmp_j &= 0) {
if (chessman[tmp_i--][tmp_j--] == who_run)
line_sum++;
if (line_sum == 4)
line_sum++;
while (line_sum != 5 && tmp_i &= 15 && tmp_j &= 15) {
if (chessman[tmp_i++][tmp_j++] == who_run)
line_sum++;
if (line_sum == 5) {
if (a == 1)
chessman[i][j] =
return who_
if (step_sum == 225) {
if (a == 1)
chessman[i][j] =
if (a == 1)
chessman[i][j] =
score_row(int i, int j, int chessman[LENGTH][LENGTH])
sum_chessmen = 0;
score = 0;
who_running = chessman[i][j];
if (j == LENGTH) {
while (chessman[i][j] == who_running) {
sum_chessmen++;
if (sum_chessmen &= 5)
score = 200000;
if (chessman[i][j] == 0) /* 没有下子,活的情况 */
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0; /* 死的情况 */
while (chessman[i][j] == who_running && j != LENGTH) {
sum_chessmen++;
j = j - sum_chessmen - 1;
while (chessman[i][j] == who_running && j != -1) {
sum_chessmen++;
if (j &= 0 && mid_j & LENGTH) {
if (chessman[i][j] == 0 && chessman[i][mid_j] == 0)
score = 18000 / POW(50, 4 - sum_chessmen);
else if ((chessman[i][j] != 0 && chessman[i][mid_j] == 0)
|| (chessman[i][j] == 0 && chessman[i][mid_j] != 0))
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
if (j & 0 && mid_j & LENGTH) {
if (chessman[i][mid_j] == 0)
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
if (j &= 0 && mid_j &= LENGTH) {
if (chessman[i][j] == 0)
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
if (j & 0 && mid_j &= LENGTH)
score = 0;
score_col(int i, int j, int chessman[LENGTH][LENGTH])
sum_chessmen = 0,
score = 0;
who_running = chessman[i][j];
if (i == LENGTH) {
while (chessman[i][j] == who_running) {
sum_chessmen++;
if (sum_chessmen &= 5)
score = 200000;
if (chessman[i][j] == 0)
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
while (chessman[i][j] == who_running) {
sum_chessmen++;
if (i == LENGTH || chessman[i][j] != who_running) {
i = i - sum_
while (chessman[i - 1][j] == who_running) {
sum_chessmen++;
if (i &= 0) {
if (chessman[i][j] == 0 && chessman[mid_i][j] == 0)
score = 18000 / POW(50, 4 - sum_chessmen);
else if ((chessman[i][j] != 0 && chessman[mid_i][j]) == 0
|| (chessman[i][j] == 0
&& chessman[mid_i][j] != 0))
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
if (i & 0 && mid_i & LENGTH) {
if (chessman[mid_i][j] == 0)
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
if (i & 0 && mid_i & LENGTH) {
if (chessman[mid_i][j] == 0)
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
if (i &= 0 && mid_i &= LENGTH) {
if (chessman[i][j] == 0)
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
score_diag_45(int i, int j, int chessman[LENGTH][LENGTH])
sum_chessmen = 0;
score = 0;
who_running = chessman[i][j];
if (i == LENGTH || j == LENGTH) {
while (chessman[i][j] == who_running && i & 1 && j & 1) {
sum_chessmen++;
if (sum_chessmen &= 5)
score = 200000;
if (chessman[i][j] == 0)
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
while (chessman[i][j] == who_running && i &= LENGTH && j &= LENGTH) {
sum_chessmen++;
i = i - sum_
j = j - sum_
while (chessman[i - 1][j - 1] == who_running) {
sum_chessmen++;
if (sum_chessmen &= 5)
score = 200000;
if (i &= 0 && j &= 0 && mid_i & LENGTH && mid_j & LENGTH) {
if (chessman[mid_i][mid_j] == 0 && chessman[i][j] == 0)
score = 18000 / POW(50, 4 - sum_chessmen);
else if ((chessman[mid_i][mid_j] == 0 && chessman[i][j] != 0)
|| (chessman[mid_i][mid_j] != 0
&& chessman[i][j] == 0))
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
if (i &= 0 && j &= 0) {
if (chessman[i][j] == 0)
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
} else if (mid_i & LENGTH && mid_j & LENGTH) {
if (chessman[mid_i][mid_j] == 0)
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
score = 0;
score_diag_135(int i, int j, int chessman[LENGTH][LENGTH])
sum_chessmen = 0;
score = 0;
who_running = chessman[i][j];
while (chessman[i][j] == who_running && j != -1 && i & LENGTH) {
sum_chessmen++;
while (chessman[i][j] == who_running && j != LENGTH) {
sum_chessmen++;
if (sum_chessmen &= 5)
score = 200000;
if (i &= 0 && j & LENGTH && mid_j &= 0 && mid_i & LENGTH) {
if (chessman[i][j] == 0 && chessman[mid_i][mid_j] == 0)
score = 18000 / POW(50, 4 - sum_chessmen);
if ((chessman[i][j] == 0 && chessman[mid_i][mid_j] != 0)
|| (chessman[i][j] != 0
&& chessman[mid_i][mid_j] == 0))
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
if (i &= 0 && j & LENGTH) {
if (chessman[i][j] == 0)
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
if (mid_j &= 0 && mid_i & LENGTH) {
if (chessman[mid_i][mid_j] == 0)
score = 2000 / POW(10, 4 - sum_chessmen);
score = 0;
total_score(int who_running, int chessman[LENGTH][LENGTH])
* 统计出在该点上的得分,who_running=1表示人的棋子,2为电脑的棋子
score = 0;
for (i = 0; i & LENGTH; i++)
for (j = 0; j & LENGTH; j++) {
if (chessman[i][j] == who_running) {
score += score_row(i, j, chessman);
score += score_col(i, j, chessman);
score += score_diag_45(i, j, chessman);
score += score_diag_135(i, j, chessman);
score(int chessman[LENGTH][LENGTH])
* 计算最终的得分数,分别考虑了在这个位置放对方棋子跟自己棋子的综合
sum1 = total_score(COMPUTER, chessman);
sum2 = total_score(PLAYER1, chessman);
return sum1 - sum2;
* 扩展-----剪枝过程
rowdt(int i, int j, int chessman[LENGTH][LENGTH])
/*在树直方向*/
midjl = j - STEP,
/*当前棋子的上方*/
midjr = j + STEP + 1;
/*当前棋子的下方棋子的下方??????*/
if (midjl & 0)
midjl = 0;
if (midjr & LENGTH)
midjr = LENGTH;
for (k = k & k++)
if (chessman[i][k] != 0)
/*如果有棋子*/
coldt(int i, int j, int chessman[LENGTH][LENGTH])
/*水平方向*/
midil = i + STEP + 1,
/*当前的右边棋子的右一个*/
midiu = i - STEP;
/*当前棋子的左一个*/
if (midiu & 0)
midiu = 0;
if (midil & LENGTH)
midil = LENGTH;
for (k = k & k++)
if (chessman[k][j] != 0)
diadt(int i, int j, int chessman[LENGTH][LENGTH])
/*右上到左下方向*/
for (k = 0; k & STEP; k++) {
if (midj & 0 || midi &= LENGTH)
if (chessman[midi][midj] != 0)
for (k = 0; k & STEP; k++) {
if (i & 0 || j &= LENGTH)
if (chessman[i][j] != 0)
vdiadt(int i, int j, int chessman[LENGTH][LENGTH])
/*左上到右下方向*/
for (k = 0; k & STEP; k++) {
if (midi & 0 || midj & 0)
if (chessman[midi][midj] != 0)
for (k = 0; k & STEP; k++) {
if (j &= LENGTH || i &= LENGTH)
if (chessman[i][j] != 0)
can_expand(int i, int j, int chessman[LENGTH][LENGTH])
if (rowdt(i, j, chessman))
if (coldt(i, j, chessman))
if (diadt(i, j, chessman))
if (vdiadt(i, j, chessman))
* 如果不能扩展,返回0
/************************************************************/

我要回帖

更多关于 双人五子棋 的文章

 

随机推荐