package day17gobang;
import javautilArrays;
public class GoBangGame {
public static final char BLANK='';
public static final char BLACK='@';
public static final char WHITE='O';
public static final int MAX = 16;
private static final int COUNT = 5;
//棋盘
private char[][] board;
public GoBangGame() {
}
//开始游戏
public void start() {
board = new char[MAX][MAX];
//把二维数组都填充‘’
for(char[] ary: board){
Arraysfill(ary, BLANK);
}
}
public char[][] getChessBoard(){
return board;
}
public void addBlack(int x, int y) throws ChessExistException{
//@
//char blank = '';
//Systemoutprintln( x +"," + y + ":" + board[y][x] + "," + BLANK);
if(board[y][x] == BLANK){// x, y 位置上必须是空的才可以添棋子
board[y][x] = BLACK;
return;
}
throw new ChessExistException("已经有棋子了!");
}
public void addWhite(int x, int y)
throws ChessExistException{
if(board[y][x] == BLANK){// x, y 位置上必须是空的才可以添棋子
board[y][x] = WHITE;
return;
}
throw new ChessExistException("已经有棋子了!");
}
//chess 棋子:'@'/'O'
public boolean winOnY(char chess, int x, int y){
//先找到y方向第一个不是 blank的棋子
int top = y;
while(true){
if(y==0 || board[y-1][x]!=chess){
//如果y已经是棋盘的边缘, 或者的前一个不是chess
//就不再继续查找了
break;
}
y--;
top = y;
}
//向回统计所有chess的个数,如果是COUNT个就赢了
int count = 0;
y = top;
while(true){
if(y==MAX || board[y][x]!=chess){
//如果找到头 或者 下一个子不是chess 就不再继续统计了
break;
}
count++;
y++;
}
return count==COUNT;
}
//chess 棋子:'@'/'O'
public boolean winOnX(char chess, int x, int y){
//先找到x方向第一个不是 blank的棋子
int top = x;
while(true){
if(x==0 || board[y][x-1]!=chess){
//如果x已经是棋盘的边缘, 或者的前一个不是chess
//就不再继续查找了
break;
}
x--;
top = x;
}
//向回统计所有chess的个数,如果是COUNT个就赢了
int count = 0;
x = top;
while(true){
if(x==MAX || board[y][x]!=chess){
//如果找到头 或者 下一个子不是chess 就不再继续统计了
break;
}
count++;
x++;
}
return count==COUNT;
}
//chess 棋子:'@'/'O'
public boolean winOnXY(char chess, int x, int y){
//先找MAX向第一个不是 blank的棋子
int top = y;
int left = x;
while(true){
if(x==0 || y==0 || board[y-1][x-1]!=chess){
//如果x已经是棋盘的边缘, 或者的前一个不是chess
//就不再继续查找了
break;
}
x--;
y--;
top = y;
left=x;
}
//向回统计所有chess的个数,如果是COUNT个就赢了
int count = 0;
x = left;
y = top;
while(true){
if(x==MAX || y==MAX || board[y][x]!=chess){
//如果找到头 或者 下一个子不是chess 就不再继续统计了
break;
}
count++;
x++;
y++;
}
return count==COUNT;
}
//chess 棋子:'@'/'O'
public boolean winOnYX(char chess, int x, int y){
//先找到x方向第一个不是 blank的棋子
int top = y;
int left = x;
while(true){
if(x==MAX-1 || y==0 || board[y-1][x+1]!=chess){
//如果x已经是棋盘的边缘, 或者的前一个不是chess
//就不再继续查找了
break;
}
x++;
y--;
top = y;
left=x;
}
//向回统计所有chess的个数,如果是COUNT个就赢了
int count = 0;
x = left;
y = top;
while(true){
if(x==0 || y==MAX || board[y][x]!=chess){
//如果找到头 或者 下一个子不是chess 就不再继续统计了
break;
}
count++;
x--;
y++;
}
return count==COUNT;
}
public boolean whiteIsWin(int x, int y) {
//在任何一个方向上赢了,都算赢
return winOnY(WHITE, x, y) ||
winOnX(WHITE, x, y) ||
winOnXY(WHITE, x, y) ||
winOnYX(WHITE, x, y);
}
public boolean blackIsWin(int x, int y) {
return winOnY(BLACK, x, y) ||
winOnX(BLACK, x, y) ||
winOnXY(BLACK, x, y) ||
winOnYX(BLACK, x, y);
}
}
#include <iostream>
#include <cstdio>
#include <cstdlib>
#define MAXSIZE 50000
using namespace std;
//树采用孩子兄弟链存储结构
typedef struct Village
{
int num; //村子编号
int intime; //深度优先遍历入栈时间
int outtime; //节点出栈时间
struct Village firstchild;
struct Village nextcousin;
}VillageNode;
typedef struct
{
int top;
VillageNode villages[MAXSIZE];
}Stack;
Stack s = (Stack )malloc(sizeof(Stack));
int time=0; //记录栈访问时间
int addNode(VillageNode root, int a, int b);
VillageNode dfsfind(VillageNode root, int va, int vb);
void popStack(VillageNode p);
void pushStack(VillageNode p);
void dfs(VillageNode root);
void ifwait(int va, int vb, int vc);
//将p节点压入栈
void pushStack(VillageNode p)
{
if(s->top>-1)
printf("当前栈顶元素为%d,",s->villages[s->top]->num);
else
printf("当前栈元素为空,");
s->villages[++s->top] = p;
time++; //栈访问次数加1
p->intime = time; //记录入栈时间
printf("入栈后元素总数为%d,入栈元素为%d,intime: %d\n",s->top+1, p->num, time);
}
//将栈顶元素弹出,并将地址保存至p指针
void popStack(VillageNode p)
{
if(s->top > -1)
{
p = s->villages[s->top];
s->top--;
time++; //栈访问次数加1
p->outtime = time;
printf("出栈元素为%d, outtime: %d,出栈后元素总数为%d,",p->num, time, s->top+1);
}
if(s->top > -1)
printf("当前栈顶元素为%d\n",s->villages[s->top]->num);
else
printf("当前栈元素为空\n");
}
VillageNode dfsfind(VillageNode root, int va)
{
if(root == NULL) //当当前节点为空时返回NULL
return NULL;
int v = root->num;
VillageNode p, q;
//curcnt++; //用于记录当前访问过的节点数
if(va == v ) //如果找到原先既有的节点,则返回该节点的指针
return root;
q = dfsfind(root->firstchild, va); //递归访问孩子节点
if(q != NULL)
return q;
//依次递归访问兄弟节点
p = root->nextcousin;
while(p != NULL)
{
q = dfsfind(p, va);
if(q != NULL)
return q;
p = p->nextcousin;
}
return NULL;
///当访问过的节点达到总数仍没有找到va 或 vb节点时,返回NULL
if(root->firstchild == NULL && root->nextcousin == NULL)
return NULL;
else
{
if(root->firstchild == NULL)
{
p = root->nextcousin;
while(p != NULL)
{
dfsfind(p);
p = p->nextcousin;
}
}
else if(root->nextcousin == NULL)
{
dfsfind(root->firstchild);
}
else
{
}
}/
}
//a必须是树中已经存在的节点
int addNode(VillageNode root, int va, int vb)
{
VillageNode vp = dfsfind(root, va); //寻找编号为a的村子
VillageNode p, q;
if(vp != NULL)
{
if(vp->num == va) //找到村子a,遍历其孩子节点
{
p = vp->firstchild;
q = vp;
if(p == NULL) //当vp节点下没有孩子节点时
{
VillageNode vn = (VillageNode) malloc(sizeof(VillageNode));
vn->firstchild = NULL;
vn->nextcousin = NULL;
vn->num = vb;
q->firstchild = vn;
return 1;
}
while(p != NULL)
{
if(p->num == vb) //当村子a存在到村子b的路时返回0
return 0;
q = p; //记录下当前节点
p = p->nextcousin; //p指向下一个节点
}
VillageNode vn = (VillageNode) malloc(sizeof(VillageNode));
vn->firstchild = NULL;
vn->nextcousin = NULL;
vn->num = vb;
q->nextcousin = vn;
return 1;
}
}
return -1;
}
void dfs(VillageNode root)
{
pushStack(root);
VillageNode p;
p = root->firstchild; //指向第一个孩子
while(p != NULL) //当孩子节点不为空时,递归访问孩子节点
{
dfs(p);
p = p->nextcousin;
}
popStack(p); //弹出栈顶元素
return;
}
void ifwait(VillageNode root, int va, int vb, int vc)
{
VillageNode VA = dfsfind(root,va);
VillageNode VB = dfsfind(root,vb);
VillageNode VC = dfsfind(root,vc);
printf("找到的a,b,c分别为:%d %d %d\n",VA->num, VB->num, VC->num);
if((VC->intime < VA->intime && VC->outtime > VA->outtime) //当VC节点的入出栈时间区间包含VA的区间
&&(VC->intime < VB->intime && VC->outtime > VB->outtime)) //且VC节点的入出栈时间区间包含VB的区间
{
//当VC是VA和VB的公共祖先时判断是否是最低公共祖先
int a[2][MAXSIZE]; //二维数组第一行存放intime 第二行存放outtime 每一列对应一个节点 从左到右
int m,n;
m = VA->intime < VB->intime VA->intime : VB->intime; //记录VA、VB入栈的最小时间
n = VA->outtime > VB->outtime VA->outtime : VB->outtime; //记录VA、VB出栈最大时间
VillageNode p = VC->firstchild;
int i=0;
while(p != NULL) //遍历VC节点所有的孩子节点 将孩子们的入出栈时间存入数组,方便二分查找
{
a[0][i] = p->intime;
a[1][i] = p->outtime;
i++;
p = p->nextcousin;
}
//二分查找[m,n]区间是否包含在其中一个孩子节点中
int low=0, high = i-1, mid;
while(low <= high)
{
mid = (low + high) / 2;
if(a[0][mid] <= m && a[1][mid] >= n) //查找到有区间包含[m,n]区间时,说明VC不是VA和VB的最低公共祖先,则跳出循环
{
printf("No\n");
return;
}
if(a[0][mid] > m) //继续在a[0][lowmid-1]中查找
high = mid - 1;
else //继续在a[0][mid+1high]中查找
low = mid + 1;
}
printf("Yes\n"); //当查找结束仍没有找到该区间,说明VC是VA。VB的最低公共祖先
}
else if((VC->intime < VA->intime && VC->outtime > VA->outtime) //当VC节点的入出栈时间区间包含VA的区间
|| (VC->intime < VB->intime && VC->outtime > VB->outtime)) //或VC节点的入出栈时间区间包含VB的区间
{
//此时VC是VA、VB其中一个节点的祖先,存在A-C-B的路径
printf("Yes\n");
}
else //当VC不是VA或VB节点的祖先时不存在A-C-B的路径
printf("No\n");
return;
}
int main()
{
int N, M, a, b, c;
printf("请输入小村个数:\n");
scanf("%d",&N);
VillageNode root = (VillageNode )malloc(sizeof(VillageNode)); //开辟指向深度优先搜索树的指针并建立深度优先搜素树
root->firstchild = NULL;
root->nextcousin = NULL;
root->num = 0;
//cnt++;
printf("接下来,请依次输入包含一条双向道路的两个端点小村的编号:\n");
while(--N)
{
scanf("%d %d", &a, &b); //读取边信息
int flag = addNode(root, a, b);
if(flag==0)
{
printf("小村%d到小村%d的路径已存在,无需再次输入,本次输入将不会被记录。\n", a, b);
N++;
}
else if(flag == 1)
printf("成功录入!%d-%d\n", a, b);
else
printf("录入失败!%d-%d\n", a, b);
}
s->top = -1;
dfs(root); //深度优先遍历一遍树
printf("请输入测试样例个数:\n");
scanf("%d", &M);
printf("请依次输入测试样例:\n");
while(M--)
{
scanf("%d %d %d", &a, &b, &c);
ifwait(root, a, b, c);
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstdlib>
#define MAXSIZE 50000
using namespace std;
//村子树节点,数据域有入栈出栈时间域、村子编号域
//树采用孩子兄弟链存储结构
typedef struct Village
{
int num; //村子编号
int intime; //深度优先遍历入栈时间
int outtime; //节点出栈时间
struct Village firstchild;
struct Village nextcousin;
}VillageNode;
typedef struct
{
int top;
VillageNode villages[MAXSIZE];
}Stack;
Stack s = (Stack )malloc(sizeof(Stack));
int time=0; //记录栈访问时间
int addNode(VillageNode root, int a, int b);
VillageNode dfsfind(VillageNode root, int va, int vb);
void popStack(VillageNode p);
void pushStack(VillageNode p);
void dfs(VillageNode root);
void ifwait(int va, int vb, int vc);
//将p节点压入栈
void pushStack(VillageNode p)
{
if(s->top>-1)
printf("当前栈顶元素为%d,",s->villages[s->top]->num);
else
printf("当前栈元素为空,");
s->villages[++s->top] = p;
time++; //栈访问次数加1
p->intime = time; //记录入栈时间
printf("入栈后元素总数为%d,入栈元素为%d,intime: %d\n",s->top+1, p->num, time);
}
//将栈顶元素弹出,并将地址保存至p指针
void popStack(VillageNode p)
{
if(s->top > -1)
{
p = s->villages[s->top];
s->top--;
time++; //栈访问次数加1
p->outtime = time;
printf("出栈元素为%d, outtime: %d,出栈后元素总数为%d,",p->num, time, s->top+1);
}
if(s->top > -1)
printf("当前栈顶元素为%d\n",s->villages[s->top]->num);
else
printf("当前栈元素为空\n");
}
VillageNode dfsfind(VillageNode root, int va)
{
if(root == NULL) //当当前节点为空时返回NULL
return NULL;
int v = root->num;
VillageNode p, q;
//curcnt++; //用于记录当前访问过的节点数
if(va == v ) //如果找到原先既有的节点,则返回该节点的指针
return root;
q = dfsfind(root->firstchild, va); //递归访问孩子节点
if(q != NULL)
return q;
//依次递归访问兄弟节点
p = root->nextcousin;
while(p != NULL)
{
q = dfsfind(p, va);
if(q != NULL)
return q;
p = p->nextcousin;
}
return NULL;
///当访问过的节点达到总数仍没有找到va 或 vb节点时,返回NULL
if(root->firstchild == NULL && root->nextcousin == NULL)
return NULL;
else
{
if(root->firstchild == NULL)
{
p = root->nextcousin;
while(p != NULL)
{
dfsfind(p);
p = p->nextcousin;
}
}
else if(root->nextcousin == NULL)
{
dfsfind(root->firstchild);
}
else
{
}
}/
}
//a必须是树中已经存在的节点
int addNode(VillageNode root, int va, int vb)
{
VillageNode vp = dfsfind(root, va); //寻找编号为a的村子
VillageNode p, q;
if(vp != NULL)
{
if(vp->num == va) //找到村子a,遍历其孩子节点
{
p = vp->firstchild;
q = vp;
if(p == NULL) //当vp节点下没有孩子节点时
{
VillageNode vn = (VillageNode) malloc(sizeof(VillageNode));
vn->firstchild = NULL;
vn->nextcousin = NULL;
vn->num = vb;
q->firstchild = vn;
return 1;
}
while(p != NULL)
{
if(p->num == vb) //当村子a存在到村子b的路时返回0
return 0;
q = p; //记录下当前节点
p = p->nextcousin; //p指向下一个节点
}
VillageNode vn = (VillageNode) malloc(sizeof(VillageNode));
vn->firstchild = NULL;
vn->nextcousin = NULL;
vn->num = vb;
q->nextcousin = vn;
return 1;
}
}
return -1;
}
void dfs(VillageNode root)
{
pushStack(root);
VillageNode p;
p = root->firstchild; //指向第一个孩子
while(p != NULL) //当孩子节点不为空时,递归访问孩子节点
{
dfs(p);
p = p->nextcousin;
}
popStack(p); //弹出栈顶元素
return;
}
void ifwait(VillageNode root, int va, int vb, int vc)
{
VillageNode VA = dfsfind(root,va);
VillageNode VB = dfsfind(root,vb);
VillageNode VC = dfsfind(root,vc);
printf("找到的a,b,c分别为:%d %d %d\n",VA->num, VB->num, VC->num);
if((VC->intime < VA->intime && VC->outtime > VA->outtime) //当VC节点的入出栈时间区间包含VA的区间
&&(VC->intime < VB->intime && VC->outtime > VB->outtime)) //且VC节点的入出栈时间区间包含VB的区间
{
//当VC是VA和VB的公共祖先时判断是否是最低公共祖先
int a[2][MAXSIZE]; //二维数组第一行存放intime 第二行存放outtime 每一列对应一个节点 从左到右
int m,n;
m = VA->intime < VB->intime VA->intime : VB->intime; //记录VA、VB入栈的最小时间
n = VA->outtime > VB->outtime VA->outtime : VB->outtime; //记录VA、VB出栈最大时间
VillageNode p = VC->firstchild;
int i=0;
while(p != NULL) //遍历VC节点所有的孩子节点 将孩子们的入出栈时间存入数组,方便二分查找
{
a[0][i] = p->intime;
a[1][i] = p->outtime;
i++;
p = p->nextcousin;
}
//二分查找[m,n]区间是否包含在其中一个孩子节点中
int low=0, high = i-1, mid;
while(low <= high)
{
mid = (low + high) / 2;
if(a[0][mid] <= m && a[1][mid] >= n) //查找到有区间包含[m,n]区间时,说明VC不是VA和VB的最低公共祖先,则跳出循环
{
printf("No\n");
return;
}
if(a[0][mid] > m) //继续在a[0][lowmid-1]中查找
high = mid - 1;
else //继续在a[0][mid+1high]中查找
low = mid + 1;
}
printf("Yes\n"); //当查找结束仍没有找到该区间,说明VC是VA。VB的最低公共祖先
}
else if((VC->intime < VA->intime && VC->outtime > VA->outtime) //当VC节点的入出栈时间区间包含VA的区间
|| (VC->intime < VB->intime && VC->outtime > VB->outtime)) //或VC节点的入出栈时间区间包含VB的区间
{
//此时VC是VA、VB其中一个节点的祖先,存在A-C-B的路径
printf("Yes\n");
}
else //当VC不是VA或VB节点的祖先时不存在A-C-B的路径
printf("No\n");
return;
}
int main()
{
int N, M, a, b, c;
printf("请输入小村个数:\n");
scanf("%d",&N);
VillageNode root = (VillageNode )malloc(sizeof(VillageNode)); //开辟指向深度优先搜索树的指针并建立深度优先搜素树
root->firstchild = NULL;
root->nextcousin = NULL;
root->num = 0;
//cnt++;
printf("接下来,请依次输入包含一条双向道路的两个端点小村的编号:\n");
while(--N)
{
scanf("%d %d", &a, &b); //读取边信息
int flag = addNode(root, a, b);
if(flag==0)
{
printf("小村%d到小村%d的路径已存在,无需再次输入,本次输入将不会被记录。\n", a, b);
N++;
}
else if(flag == 1)
printf("成功录入!%d-%d\n", a, b);
else
printf("录入失败!%d-%d\n", a, b);
}
s->top = -1;
dfs(root); //深度优先遍历一遍树
printf("请输入测试样例个数:\n");
scanf("%d", &M);
printf("请依次输入测试样例:\n");
while(M--)
{
scanf("%d %d %d", &a, &b, &c);
ifwait(root, a, b, c);
}
return 0;
}
这个我也看晕了,编号和下标混着挺难理解的。我自己写了一个:
#include <stdioh>
#include <stdlibh>
int main()
{
int i,count,remain,total[25][2];
//total为二维数组,第二维的第一个地址存人的编号,第二个存这个人当前的状态。
for(i=0;i<25;i++)
{
total[i][0]=i; //数组中下标为i的人的编号。
total[i][1]=0; //数组总下标为i的人的状态:已经出列就置1,否则置0
}
i=0; //初始编号为0
count=0; //已经数的人数,count==3时此人就出列
remain=25; //最后剩下的人数
while(remain>0) //所有人循环数直到全部出列 (如果最后要剩下两人条件就改成remain>2)
{
if(total[i%25][1]==0) //如果当前的人状态为0,表示没出列,所以要数,如果为1,表示已经出列了,就不对他计数了。i%25是为了循环,比如数到25的话就变成了编号为0的人,i 一直往前数就能保证在25人中循环计数。
{
count++;
}
if(count==3) //如果数到3,这个人就要出列了
{
total[i%25][1]=1; //此人状态变成1,即出列
remain--; //剩余的人数减一
count=0; //重新从0开始计数
printf("%d ",total[i%25][0]); //输出这个人的编号
}
i++; // i 增1 保持循环计数。
}
return 0;
}
这个解析很清楚了,先理解SCANF和二维数组的原理
scanf将输入值复制到后面第二个参数所指向的位置,也就是说第二个参数是一个指针
用其名字来引用二维数组即x[0][0]到X[2][1]表示的是六个指针,指向数组存储范围的指针
而如果不写第二个括号比如X[0]就是默认指向第一个元素即X[0][0]
那么很容易就得出答案,scanf输入的是一个%d 就是一个INT数值,那么只能填充一行中的一位
而未被填充的哪一位就还是初始的0
欢迎分享,转载请注明来源:表白网
评论列表(0条)