UVA-1589 象棋(模拟)

题目:(传送门)

给出一个象棋的残局,下一步是黑棋走,判断黑棋是不是被将死。

思路:

读完这个题,知道是一个模拟题,然后想到用两个二维数组来模拟棋盘,一个(mp数组)用来存残局,一个(res数组)用来处理红棋在棋盘上产生的对黑棋的限制。

将红棋的马、车、炮、将写成函数来分别处理。这样处理完之后,判断一下黑棋的四周是不是有可以走的格子,有的话不是将死,没有的是就是被将死了。

1、可以将车和将写成一个函数来处理,这里可以标记与棋子处于同一行和同一列中的格子,如下图:

红色圈出来的部分不能走,注意马上边的格子是可以走的,而如果和车一行的只有对方的将,那么这一行都不能走。

2、对马的处理,如下图:

同理,红色的部分不能走,注意马有蹩腿的情况出现如上右图

3、对炮棋的处理最为复杂,具体情况如图:

如上右图中绿色的部分是可以走的,左图中的红色部分是不可以走的。

代码:(略长)

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define MAX 1e9;
#define FRE() freopen("in.txt","r",stdin)
#define FRO() freopen("out.txt","w",stdout)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int maxn = 200000;//G-general-1  R-chariot-2 C-cannon-3 H-horse-4 Black-5
map<char,int> key;
int mp[11][10],res[11][10];
int N,bx,by;
struct T{
    char ch;
    int x,y;
}t[10];

bool isIn(int x,int y) {//判断是不是在棋盘的范围内
    if(x>=1 && x<=10 && y>=1 && y<=9) {
        return true;
    }
    return false;
}

void makeGR(int x,int y) {//处理车和将的关系
    if(isIn(x,y)) {
        for(int i=x-1; i>=1; i--) { //Up
            res[i][y] = -1;
            if(mp[i][y]!=0 && mp[i][y]!=‘B‘) {//从当前位置起到另外的第一个棋子(不包括黑棋)中间的位置都是不可以走的
                break;
            }
        }
        for(int i = x+1; i<=3; i++) { //Down
            res[i][y] = -1;
            if(mp[i][y]!=0 && mp[i][y]!=‘B‘) {
                break;
            }
        }
        for(int i = y-1; i>=1; i--) { //Left
            res[x][i] = -1;
            if(mp[x][i]!=0 && mp[x][i]!=‘B‘) {
                break;
            }
        }
        for(int i = y+1; i<=9; i++) { //Right
            res[x][i] = -1;
            if(mp[x][i]!=0 && mp[x][i]!=‘B‘) {
                break;
            }
        }
    }
}

void makeH(int x,int y) {//处理马棋
    if(isIn(x-2,y-1) && mp[x-1][y]==0) { //Up//排除蹩腿的情况一共八个方向
        res[x-2][y-1] = -1;
    }
    if(isIn(x-2,y+1) && mp[x-1][y]==0){
        res[x-2][y+1] = -1;
    }
    if(isIn(x+2,y-1) &&  mp[x+1][y]==0) { //Down
        res[x+2][y-1] = -1;
    }
    if(isIn(x+2,y+1) &&  mp[x+1][y]==0){
        res[x+2][y+1] = -1;
    }
    if(isIn(x-1,y-2) && mp[x][y-1]==0){//Left
        res[x-1][y-2] = -1;
    }
    if(isIn(x+1,y-2) && mp[x][y-1]==0){
        res[x+1][y-2] = -1;
    }
    if(isIn(x-1,y+2) && mp[x][y+1]==0) { //Right
        res[x-1][y+2] = -1;
    }
    if(isIn(x+1,y+2) && mp[x][y+1]==0){
        res[x+1][y+2] = -1;
    }
}

void makeC(int x,int y) {//处理炮棋
    if(x==1&&(y>=4&&y<=6)) {
        if(mp[2][y]!=0 && mp[2][y]!=‘B‘){
            res[3][y] = -1;
        }
    }
    int tx=0,ty=0;
    for(int i = x-1; i>=1; i--) { //Up
        if(isIn(i,y) && mp[i][y]!=0 && mp[i][y]!=‘B‘) {//寻找与炮棋一行的棋子的位置(不包括黑棋)
            tx = i,ty = y; //cout<<"GG"<<endl;
            break;
        }
        if(isIn(i,y) && mp[i][y]==‘B‘)
            return;
    }
    //<<"TX: "<<tx<<"   TY: "<<ty<<endl;
    for(int i = tx-1; i>=1; i--) { //Up标记从找到的棋子到棋盘边缘的格子
       // if(isIn(i,y) && (mp[i][y]==0 || mp[i][y]==‘B‘)) {
            res[i][y]=-1;
        //}
        if(isIn(i,y) && mp[i][y]!=0 && mp[i][y]!=‘B‘){//出现第二个格子就停止
            break;
        }
    }
    for(int i=y-1; i>=1; i--) { //Left
        if(isIn(x,i) && mp[x][i]!=0 && mp[x][i]!=‘B‘) {
            tx=x, ty = i;
            break;
        }
        if(isIn(x,i) && mp[x][i]==‘B‘){
            return;
        }
    }
    for(int i=ty-1; i>=1; i--) { //Left
        //if(isIn(x,i) && (mp[x][i]==0 || mp[x][i]==‘B‘)) {
            res[x][i] = -1;
        //}
        if(isIn(x,i) && mp[x][i]==0 && mp[x][i]!=‘B‘){
            break;
        }
    }
    for(int i = y+1; i<=9; i++) {//Right
        if(isIn(x,i) && mp[x][i]!=0 && mp[x][i]!=‘B‘) {
            tx = x,ty=i;
            break;
        }
        if(isIn(x,i) && mp[x][i]==‘B‘){
            return;
        }
    }
    for(int i = y+1; i<=9; i++){//Right
        //if(isIn(x,i) && (mp[x][i]==0 || mp[x][i]==‘B‘)){
            res[x][i] = -1;
        //}
        if(isIn(x,i) && mp[x][i]==0 && mp[x][i]!=‘B‘){
            break;
        }
    }
}

bool in(int x,int y){//判断黑棋是不是在规定的格子内部
    if(x>=1 && x<=3 && y>=4 && y<=6){
        return true;
    }
    return false;
}

bool judge(int x,int y){//判断有没有被将死
    bool ok = false;
    if(in(x-1,y) && res[x-1][y]!=-1) ok = true;
    if(in(x+1,y) && res[x+1][y]!=-1) ok = true;
    if(in(x,y-1) && res[x][y-1]!=-1) ok = true;
    if(in(x,y+1) && res[x][y+1]!=-1) ok = true;
    return ok;
}

 void check1(){
    for(int i = 1; i<=10; i++){
        for(int j = 1; j<=9; j++){
            printf("%2d ",res[i][j]);
        }
        printf("\n");
    }
 }

  void check2(){
    for(int i = 1; i<=10; i++){
        for(int j = 1; j<=9; j++){
            printf("%2d ",mp[i][j]);
        }
        printf("\n");
    }
 }

int main() {
    //FRE();scanf("%d%d%d",&N,&bx,&by)
    //FRO();
    while(cin>>N>>bx>>by) {//必须要吐槽一下,这里的输出太懵逼了,用scanf就出错,用cin就AC......
        //printf("bx:%d  by:%d\n",bx,by);
        memset(mp,0,sizeof(mp));
        memset(res,0,sizeof(res));
        if(N==0&&bx==0&&by==0) {
            break;
        }
        mp[bx][by] = ‘B‘;
        char ch;
        int rx,ry;

        for(int i = 0; i<N; i++) {
            getchar();
            cin>>ch>>rx>>ry;
            //scanf("%c %d %d",&ch,&rx,&ry);
            //printf("ch:%c rx:%d ry:%d\n",ch,rx,ry);
            mp[rx][ry] = ch;
            t[i] = T{ch,rx,ry};
        }

        for(int i = 0; i<N; i++){
            ch = t[i].ch;
            rx = t[i].x;
            ry = t[i].y;
            if(ch==‘R‘ || ch==‘G‘) {
                makeGR(rx,ry);
            }
            else if(ch==‘H‘) {
                makeH(rx,ry);
            }
            else if(ch==‘C‘) {
                makeC(rx,ry);
            }
        }
//        check2();
//        cout<<endl<<endl;
//        check1();
        if(judge(bx,by)){
            printf("NO\n");
        }else{
            printf("YES\n");
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/sykline/p/10269154.html

时间: 2024-10-16 00:51:59

UVA-1589 象棋(模拟)的相关文章

UVa 1589 Xiangqi(模拟 HDU4121)

题意  给你一个黑方被将军的象棋残局  判断红方是否已经把黑方将死 模拟题  注意细节就行了  看黑方的将是否四个方向都不能走 #include<cstdio> #include<cstring> using namespace std; const int N = 12; char brd[N][N]; int dx[] = { -1, 1, 0, 0}, dy[] = {0, 0, -1, 1}; int hx[] = { -2, -1, -2, -1, 1, 2, 1, 2}

UVA 1589:Xiangqi (模拟 Grade D)

题目: 象棋,黑棋只有将,红棋有帅车马炮.问是否死将. 思路: 对方将四个方向走一步,看看会不会被吃. 代码: 很难看……WA了很多发,还越界等等. #include <cstdio> #include <cstring> #include <cstdlib> char graph[13][13]; int go[4][2] = {{1,0},{0,1},{-1,0},{0,-1}}; bool inBlackPalace(int x, int y) { return

UVA 1589 象棋

题意: 给出一个黑方的将, 然后 红方有 2 ~ 7 个棋子, 给出摆放位置,问是否已经把黑将将死, 红方已经将军. 分析: 分情况处理, 车 马 炮, 红将情况跟车是一样的. 建一个数组board保存棋局, 然后建一个数组moveable用来算出黑将当前位置能走的格子(1可走, 0不可走, 一开始都是1), 判断一下黑将上下左右四个方位是否能走, 而且走了之后算一下当前位置moveable是否0即可. 代码: 1 #include <bits/stdc++.h> 2 using namesp

UVA - 1589 Xiangqi (模拟)

Xiangqi Problem Description Xiangqi is one of the most popular two-player board games in China. The game represents a battle between two armies with the goal of capturing the enemy's "general" piece. In this problem, you are given a situation of

UVA 712(二叉树模拟)

L - S-Trees Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Appoint description:  System Crawler  (2014-04-01) Description  S-Trees  A Strange Tree (S-tree) over the variable set  is a binary tree representing a B

UVA 1589 Xiangqi(仔细的模拟)

题意:中国象棋大家都玩过,就是基本规则,只有将,帅,车,马,炮. 解题思路: 思路是把各个棋子能攻击到的位置在judge数组相应的位置上标记出来 首先考虑马蹩马腿的情况,这个比较好考虑,注意不要越界就行了. 车,不能穿过自己方的车,马,炮,帅.但范围可以穿过'将',因为'将'下一步会移动. 炮,不可以用'将'作为炮架,其余都可以,因为'将'下一步会移动. 帅,情况很简单.一条线. 要注意的是,每个棋子的攻击范围,是必须到另一个棋子的位置的 考虑数据 3 1 5 R 1 1 R 2 5 G10 5

1589象棋(大模拟)

题意:黑棋只有一个“将”,红棋有“马”,“炮”,“车”,“帅”中的几种,问黑棋是否没有被红棋将军. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #define repu(i,a,b) for(int i=a;i<b;i++) #define mem(a) memset(a,0,sizeof(a

UVA 246 - 10-20-30 (模拟+STL)

UVA 246 - 10-20-30 题目链接 题意:给52张的扑克堆,先从左往右发7张牌,之后连续不断从左往右发7张牌,如果有牌堆形成了以下3种情况(按顺序判断): 1.头两张+尾一张和为10或20或30 2.头一张+尾两张和为10或20或30 3.尾三张和为10或20或30 就把这三张牌拿走,放到总牌堆底(这步要不断执行直到不再满足条件或牌堆没了) 如果有一个牌堆因为这个操作被取完了,那么以后将不在这个位置发牌. 如果最后7个牌堆都可以消掉,那么赢,总牌堆用完,那么输,否则平(即不断循环)

UVa 11988 (数组模拟链表) Broken Keyboard (a.k.a. Beiju Text)

题意: 模拟一个文本编辑器,可以输入字母数字下划线,如果遇到'['则认为是Home键,如果是']'则认作End键. 问最终屏幕上显示的结果是什么字符串. 分析: 如果在数组用大量的移动字符必然很耗时.所以next数组表示显示屏中s[i]右边的字符编号,变量cur模拟光标,即当前光标位于s[cur]的右边. 变量last记录显示屏最后一个字符的下标. 我理解的连接的情况应该是这样子的: 1 //#define LOCAL 2 #include <cstdio> 3 #include <cs

uva 1589 by sixleaves

坑爹的模拟题目.自己对于这种比较复杂点得模拟题的能力概述还不够,还多加练习.贴别是做得时候一直再想如何检查车中间有没有棋子,炮中间有没有棋子.到网上参考别人的代码才发先这么简单的办法,自己尽然想不到.多加练习,总结下该题目吧.   1 #include <stdio.h>  2 #include <string.h>  3 #define N 12  4   5 char brd[N][N];  6 int dx[] = {1,-1,0,0}, dy[] = {0,0,1,-1};