package pers.robert.lanqiaobeizhenti129;
import java.util.Scanner;
/**
* 13.纵横放火柴游戏
【编程题】(满分34分)
这是一个纵横火柴棒游戏。如图[1.jpg],在3x4的格子中,游戏的双方轮流放置火柴棒。其规则是:
1. 不能放置在已经放置火柴棒的地方(即只能在空格中放置)。
2. 火柴棒的方向只能是竖直或水平放置。
3. 火柴棒不能与其它格子中的火柴“连通”。所谓连通是指两根火柴棒可以连成一条直线,
且中间没有其它不同方向的火柴“阻拦”。
例如:图[1.jpg]所示的局面下,可以在C2位置竖直放置(为了方便描述格子位置,图中左、下都添加了标记),
但不能水平放置,因为会与A2连通。同样道理,B2,B3,D2此时两种方向都不可以放置。但如果C2竖直放置后,
D2就可以水平放置了,因为不再会与A2连通(受到了C2的阻挡)。
4. 游戏双方轮流放置火柴,不可以弃权,也不可以放多根。直到某一方无法继续放置,则该方为负(输的一方)。
游戏开始时可能已经放置了多根火柴。
你的任务是:编写程序,读入初始状态,计算出对自己最有利的放置方法并输出。
如图[1.jpg]的局面表示为:
00-1
-000
0100
即用“0”表示空闲位置,用“1”表示竖直放置,用“-”表示水平放置。
【输入、输出格式要求】
用户先输入整数 n(n<100), 表示接下来将输入 n 种初始局面,每种局面占3行(多个局面间没有空白行)。
程序则输出:每种初始局面情况下计算得出的最佳放置法(行号+列号+放置方式)。
例如:用户输入:
2
0111
-000
-000
1111
----
0010
则程序可以输出:
00-
211
不难猜出,输出结果的含义为:
对第一个局面,在第0行第0列水平放置
对第二个局面,在第2行第1列垂直放置
注意:
行号、列号都是从0开始计数的。
对每种局面可能有多个最佳放置方法(解不唯一),只输出一种即可。
例如,对第一个局面,001 也是正解;最第二个局面,201也是正解。
* @author Robert
*
*/
public class The013PutFireDemo1 {
public static boolean isOk(char[][] state, int i, int j) {
if (state[i][j] == '-') {
for (int j2 = j + 1; j2 < 4; j2++) {
//检查右边是不是‘-’
if (state[i][j2] == '-') {
return false;
} else if (state[i][j2] == '1') {
return true;
}
}
for (int j2 = j - 1; j2 >= 0; j2--) {
if (state[i][j2] == '-') {
return false;
} else if (state[i][j2] == '1') {
return true;
}
}
} else if (state[i][j] == '1') {
for (int i2 = i + 1; i2 < 3; i2++) {
if (state[i2][j] == '1') {
return false;
} else if (state[i2][j] == '-') {
return true;
}
}
for (int i2 = i - 1; i2 >= 0; i2--) {
if (state[i2][j] == '1') {
return false;
} else if (state[i2][j] == '-') {
return true;
}
}
}
return true;
}
private static void jasdklf(char[][] state) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
if (state[i][j] == '0') {
state[i][j] = '-';
if (isOk(state, i, j)) {
System.out.println(i + "" + j + '-');
return;
}
state[i][j] = '0';
state[i][j] = '1';
if (isOk(state, i, j)) {
System.out.println(i + "" + j + '1');
return;
}
state[i][j] = '0';
}
}
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
scanner.nextLine();
char[][] state = new char[3][4];
String s;
while ((n--) > 0) {
for (int i = 0; i < 3; i++) {
s = scanner.nextLine();
for (int j = 0; j < 4; j++) {
state[i][j] = s.charAt(j);
}
}
jasdklf(state);
}
}
}
分析:1.sc.nextInt()之后如果还有sc.nextLine(),那么第二个将不会产生效果
如过在sc.nextInt()之后还需要输入一段字符串,则在sc.nextLine()之前再添加一个sc.nextLine(),那么这里第二个sc.nextLine()才会生效
package pers.robert.lanqiaobeizhenti129;
import java.util.Scanner;
public class test {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
String n1 = scanner.nextLine();
System.out.println(n+":"+n1); }
/**
*
* in:5
abc
out:5
*/
}
2、这里只能在二维数组中从上往下找到第一个可以放置的位置和放置方式(局限)
方法2:
package pers.robert.lanqiaobeizhenti129;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* 13.纵横放火柴游戏
【编程题】(满分34分)
这是一个纵横火柴棒游戏。如图[1.jpg],在3x4的格子中,游戏的双方轮流放置火柴棒。其规则是:
1. 不能放置在已经放置火柴棒的地方(即只能在空格中放置)。
2. 火柴棒的方向只能是竖直或水平放置。
3. 火柴棒不能与其它格子中的火柴“连通”。所谓连通是指两根火柴棒可以连成一条直线,
且中间没有其它不同方向的火柴“阻拦”。
例如:图[1.jpg]所示的局面下,可以在C2位置竖直放置(为了方便描述格子位置,图中左、下都添加了标记),
但不能水平放置,因为会与A2连通。同样道理,B2,B3,D2此时两种方向都不可以放置。但如果C2竖直放置后,
D2就可以水平放置了,因为不再会与A2连通(受到了C2的阻挡)。
4. 游戏双方轮流放置火柴,不可以弃权,也不可以放多根。直到某一方无法继续放置,则该方为负(输的一方)。
游戏开始时可能已经放置了多根火柴。
你的任务是:编写程序,读入初始状态,计算出对自己最有利的放置方法并输出。
如图[1.jpg]的局面表示为:
00-1
-000
0100
即用“0”表示空闲位置,用“1”表示竖直放置,用“-”表示水平放置。
【输入、输出格式要求】
用户先输入整数 n(n<100), 表示接下来将输入 n 种初始局面,每种局面占3行(多个局面间没有空白行)。
程序则输出:每种初始局面情况下计算得出的最佳放置法(行号+列号+放置方式)。
例如:用户输入:
2
0111
-000
-000
1111
----
0010
则程序可以输出:
00-
211
不难猜出,输出结果的含义为:
对第一个局面,在第0行第0列水平放置
对第二个局面,在第2行第1列垂直放置
注意:
行号、列号都是从0开始计数的。
对每种局面可能有多个最佳放置方法(解不唯一),只输出一种即可。
例如,对第一个局面,001 也是正解;最第二个局面,201也是正解。
* @author Robert
*
*/
public class The013PutFireDemo2 {
static boolean flag = false; // 用来标记是否连通
static boolean flag2 = false; // 用来标记是否没有结果, 如果没有结果输出"空";
// 初始化数组
public static void init(List<char[][]> lis,String[] s,int n){
for(int i=0;i<n;i++){
for(int j=i*3;j<i*3+3;j++){
//***************这里只要不满足三个一组,就会被逐个添加到list中,并且满足了3个一组的时候就会i+1,即调到下一站一组
lis.get(i)[j%3] = s[j].toCharArray();
}
}
}
// 创建n个数组 初始化,并存入lis
public static void input(List<char[][]> lis,int n){
Scanner scan = new Scanner(System.in);
for(int i=1;i<=n;i++){ // 创建n个数组
lis.add(new char[3][4]);
}
String[] s = new String[n*3]; //每个数组放3行字符串,那么n个数组需要存放3*n行字符串
for(int i=0;i<n*3;i++){ // 行到输入的数据
s[i] = scan.nextLine();
}
init(lis,s,n); // 用输入的数据 初始化每个数组
}
// c='1' 检查列上侧是否连通
public static boolean colU(char[][] m,int i,int j,char c){
if(i<0){
flag = true; // 都不连通
return flag;
}
if(m[i][j]=='0'){
return colU(m,i-1,j,c);
}else if(m[i][j]=='1'){
flag = false; // 有一个 '1' 则连通
return flag;
}else if(m[i][j]=='-'){
flag = true; // 有一个 '-' 则不连通
return flag;
}
return flag;
}
// c='1' 检查列下侧是否连通
public static boolean colD(char[][] m,int i,int j,char c){
if(i>=m.length){
flag = true; // 都不连通
return flag;
}
if(m[i][j]=='0'){
return colD(m,i+1,j,c);
}else if(m[i][j]=='1'){
flag = false; // 有一个 '1' 则连通
return flag;
}else if(m[i][j]=='-'){
flag = true; // 有一个 '-' 则不连通
return flag;
}
return flag;
}
// c='-' 检查行左侧是否连通
public static boolean rowL(char[][] m,int i,int j,char c){
if(j<0){
flag = true; // 都不连通
return flag;
}
if(m[i][j]=='0'){
return rowL(m,i,j-1,c);
}else if(m[i][j]=='1'){
flag = true; // 有一个 '1' 则不连通
return flag;
}else if(m[i][j]=='-'){
flag = false; // 有一个 '-' 则连通
return flag;
}
return flag;
}
// c='-' 检查行右侧是否连通
public static boolean rowR(char[][] m,int i,int j,char c){
if(j>=m[i].length){
flag = true; // 都不连通
return flag;
}
if(m[i][j]=='0'){
return rowR(m,i,j+1,c);
}else if(m[i][j]=='1'){
flag = true; // 有一个 '1' 则不连通
return flag;
}else if(m[i][j]=='-'){
flag = false; // 有一个 '-' 则连通
return flag;
}
return flag;
}
// 当c='1'时 检查是否连通1111111111111111111
public static boolean check1(char[][] m, int i, int j, char c) {
if(colU(m,i,j,c)&&colD(m,i,j,c)){ // 是 '1' 时 检查(上下)是否连通
flag = true;
}else{
return false;
}
return flag;
}
// 当c='-'时 检查是否连通-------------------
public static boolean check2(char[][] m, int i, int j, char c) {
if(rowL(m,i,j,c)&&rowR(m,i,j,c)){ // 是 '-' 时 检查(左右)是否连通
flag = true;
}else{
return false;
}
return flag;
}
// 检测并添加元素
public static void calc2(char[][] m,int i,int j){
if(check1(m, i, j, '1')){ // 等于'1'时,行列都不连通
m[i][j] = '1'; // 则添加元素
}else if(check2(m, i, j, '-')){// 等于'-'时,行列都不连通
m[i][j] = '-';// 则添加元素
}else{
flag2 = true; // 表示无结果
}
}
// 计算函数的入口
public static void calc(char[][] m){
for(int i=0;i<m.length;i++){
for(int j=0;j<m[i].length;j++){
if(m[i][j]=='0'){
calc2(m,i,j); // 进入检测函数
}
if(flag){
String temp = i+""+j+""+m[i][j];
System.out.println(temp);
flag2 = false; // 如果有元素添加,那么就不为空!下边的就不必输出"空"值
break; // 如果添加过元素,则退出循环
}
}
if(flag){ // 如果添加过元素,则退出循环
flag = false;
break;
}
}
if(flag2){ // 如果无结果,则添加空
System.out.println("空");
flag2 = false; // 修改标记位
}
}
// 主函数
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
List<char[][]> lis = new ArrayList<char[][]>(); // 存放每个数组
System.out.print("输入整数 n(n<100):");
// 创建n个数组 初始化,并存入lis
input(lis,scan.nextInt());
// 计算函数的入口, 单独去每个数组去测试
for(int i=0;i<lis.size();i++){
calc(lis.get(i));
}
}
}
分析:
init(lis,s,n); // 用输入的数据 初始化每个数组
// 初始化数组
public static void init(List<char[][]> lis,String[] s,int n){
for(int i=0;i<n;i++){
for(int j=i*3;j<i*3+3;j++){
//***************这里只要不满足三个一组,就会被逐个添加到list中,并且满足了3个一组的时候就会i+1,即调到下一站一组
lis.get(i)[j%3] = s[j].toCharArray();
}
}
}