我正在研究Java中的河内塔问题。我选择使用Stacks作为钉子并且除了移动方法之外一切都有效。我有规范和JUnit测试类,目前我正在通过7个测试中的6个但是在移动测试中失败了。规格如下:
这是我的Towers
课程:
package edu.metrostate.ics240.p2.towers;
import java.util.Stack;
public class Towers {
private static final int DEFAULT_SIZE = 5;
private static final int MAX_SIZE = 64;
private static final int MIN_PEG = 1;
private static final int MAX_PEG = 3;
private static Stack<Integer>[] tower = new Stack[4];
private int numOfRings;
public Towers(int n) {
if (n < 1 || n > MAX_SIZE)
throw new IllegalArgumentException(
String.format("Number of rings (%s) cannot be less than 1 or exceed 64 ", n));
numOfRings = n;
tower[1] = new Stack<Integer>();
tower[2] = new Stack<Integer>();
tower[3] = new Stack<Integer>();
for (int i = 1; i <= numOfRings; i++)
tower[1].push(i);
}
public Towers() {
numOfRings = DEFAULT_SIZE;
tower[1] = new Stack<Integer>();
tower[2] = new Stack<Integer>();
tower[3] = new Stack<Integer>();
for (int i = 1; i <= numOfRings; i++)
tower[1].push(i);
}
private static void pegCheck(int pegNumber){
if (pegNumber < MIN_PEG || pegNumber > MAX_PEG)
throw new IllegalArgumentException(
String.format("Peg number (%s) cannot be less than 1 or exceed 3 ", pegNumber));
}
public int getRingCount(int pegNumber) {
pegCheck(pegNumber);
switch (pegNumber) {
case 1:
if (tower[1].isEmpty())
return 0;
else
return tower[1].size();
case 2:
if (tower[2].isEmpty())
return 0;
else
return tower[2].size();
case 3:
if (tower[3].isEmpty())
return 0;
else
return tower[3].size();
default:
return 0;
}
}
public int getTopDiameter(int pegNumber) {
pegCheck(pegNumber);
switch (pegNumber) {
case 1:
if(getRingCount(1) > 0){
return tower[1].get(tower[1].peek() - tower[1].size());
}else
return 0;
case 2:
if(getRingCount(2) > 0){
return tower[2].get(tower[2].peek() - tower[2].size());
}else
return 0;
case 3:
if(getRingCount(3) > 0){
return tower[3].get(tower[3].peek() - tower[3].size());
}else
return 0;
default:
return 0;
}
}
public boolean move(int startPeg, int endPeg) {
pegCheck(startPeg);
pegCheck(endPeg);
Stack<Integer> startTower = tower[startPeg];
Stack<Integer> endTower = tower[endPeg];
if (getRingCount(startPeg) > 0 && endPeg != startPeg && getRingCount(endPeg) > 0 && getTopDiameter(startPeg) < getTopDiameter(endPeg)) {
int topRing = startTower.pop();
endTower.push(topRing);
return true;
}else
return false;
}
}
最后是JUnit测试:
import static org.junit.Assert.*;
import org.junit.Test;
import edu.metrostate.ics240.p2.towers.*;
import java.util.Random;
public class TowersTest {
private static final int MAX_NUM_RINGS = 64;
private static final long SEED = 20170604001L;
private static final Random RAND = new Random(SEED);
@Test
public void testDefaultConstruction() {
Towers t = new Towers();
assertEquals(5, t.getRingCount(1));
assertEquals(0, t.getRingCount(2));
assertEquals(0, t.getRingCount(3));
assertEquals(1, t.getTopDiameter(1));
assertEquals(0, t.getTopDiameter(2));
assertEquals(0, t.getTopDiameter(3));
}
@Test
public void testConstruction() {
int numRings = RAND.nextInt(MAX_NUM_RINGS);
Towers t = new Towers(numRings);
assertEquals(numRings, t.getRingCount(1));
assertEquals(0, t.getRingCount(2));
assertEquals(0, t.getRingCount(3));
assertEquals(1, t.getTopDiameter(1));
assertEquals(0, t.getTopDiameter(2));
assertEquals(0, t.getTopDiameter(3));
}
@Test
public void testMove() {
int numRings = RAND.nextInt(64);
Towers t = new Towers(numRings);
assertTrue(t.move(1, 2));
assertEquals(numRings - 1, t.getRingCount(1));
assertEquals(1, t.getRingCount(2));
assertEquals(0, t.getRingCount(3));
assertEquals(2, t.getTopDiameter(1));
assertEquals(1, t.getTopDiameter(2));
assertEquals(0, t.getTopDiameter(3));
assertTrue(t.move(1, 3));
assertEquals(numRings - 2, t.getRingCount(1));
assertEquals(1, t.getRingCount(2));
assertEquals(1, t.getRingCount(3));
assertEquals(3, t.getTopDiameter(1));
assertEquals(1, t.getTopDiameter(2));
assertEquals(2, t.getTopDiameter(3));
}
@Test
public void testInvalidConstructor(){
Towers t = null;
try {
t = new Towers(0); // illegal value
fail("Expected exception");
} catch (IllegalArgumentException iae) {
// expected
}
try {
t = new Towers(MAX_NUM_RINGS + 1); // illegal value
fail("Expected exception");
} catch (IllegalArgumentException iae) {
// expected
}
}
@Test
public void testPreconditionGetRingCount() {
Towers t = new Towers();
try {
t.getRingCount(0);
fail("Exception expected");
} catch (IllegalArgumentException iae) {
// expected
}
try {
t.getRingCount(4);
fail("Exception expected");
} catch (IllegalArgumentException iae) {
// expected
}
}
@Test
public void testPreconditionTopRing() {
Towers t = new Towers();
try {
t.getTopDiameter(0);
fail("Exception expected");
} catch (IllegalArgumentException iae) {
// expected
}
try {
t.getTopDiameter(4);
fail("Exception expected");
} catch (IllegalArgumentException iae) {
// expected
}
}
@Test
public void testIllegalMoves(){
Towers t = new Towers();
t.move(1, 2);
t.move(1, 3);
assertFalse(t.move(1, 1)); // can't move to itself
assertFalse(t.move(1, 2)); // moving larger ring to smaller
assertFalse(t.move(1, 3)); // moving larger ring to smaller
assertFalse(t.move(3, 2));
}
}
我想我知道我的问题在哪里。如果getTopDiameter()
,则getRingCount(pegNum) > 0
的前提条件返回顶部环大小,但如果堆栈为空或者挂钩上没有环,则返回0。由于tower[1]
是唯一使用响铃初始化而另外两个不挂起的挂钩,getTopDiameter()
会返回0,因为当前tower[2]
和tower[3]
上没有响铃。在move()
方法中,其中一个先决条件要求getTopdiameter(startPeg)
小于getTopDiamater(endPeg)
,但如果endPeg
初始化为0环且因此为空getTopDiamater(endPeg)
返回0,在这种情况下显然不小于1。我只是无法弄清楚这一点。非常感谢任何帮助,谢谢你提前!
更新 通过所有测试用例的修订代码:
package edu.metrostate.ics240.p2.towers;
import java.util.Stack;
public class Towers {
private static final int DEFAULT_SIZE = 5;
private static final int MAX_SIZE = 64;
private static final int MIN_PEG = 1;
private static final int MAX_PEG = 3;
@SuppressWarnings("unchecked")
private static Stack<Integer>[] tower = new Stack[4];
private int numOfRings;
public Towers(int n) {
if (n < 1 || n > MAX_SIZE)
throw new IllegalArgumentException(
String.format("Number of rings (%s) cannot be less than 1 or exceed 64 ", n));
numOfRings = n;
tower[1] = new Stack<Integer>();
tower[2] = new Stack<Integer>();
tower[3] = new Stack<Integer>();
for (int i = numOfRings; i >= 1; i--)
tower[1].push(i);
}
public Towers() {
numOfRings = DEFAULT_SIZE;
tower[1] = new Stack<Integer>();
tower[2] = new Stack<Integer>();
tower[3] = new Stack<Integer>();
for (int i = numOfRings; i >= 1; i--)
tower[1].push(i);
}
private static void pegCheck(int pegNumber) {
if (pegNumber < MIN_PEG || pegNumber > MAX_PEG)
throw new IllegalArgumentException(
String.format("Peg number (%s) cannot be less than 1 or exceed 3 ", pegNumber));
}
public int getRingCount(int pegNumber) {
pegCheck(pegNumber);
if (tower[pegNumber].isEmpty()) {
return 0;
} else
return tower[pegNumber].size();
}
public int getTopDiameter(int pegNumber) {
pegCheck(pegNumber);
if (getRingCount(pegNumber) > 0) {
return tower[pegNumber].get(tower[pegNumber].size() - 1);
}
return 0;
}
public boolean move(int startPeg, int endPeg) {
pegCheck(startPeg);
pegCheck(endPeg);
if (endPeg != startPeg) {
if (getRingCount(startPeg) > 0) {
if (getRingCount(endPeg) == 0 || getTopDiameter(startPeg) < getTopDiameter(endPeg)) {
int topRing = tower[startPeg].pop();
tower[endPeg].push(topRing);
return true;
}
}
}
return false;
}
}
答案 0 :(得分:1)
你说:
在move()方法中,前提条件之一要求getTopdiameter(startPeg)小于getTopDiamater(endPeg),但如果endPeg初始化为0环且因此为空,则getTopDiamater(endPeg)返回0,这显然不是在这种情况下小于1
但是,如果您阅读了所提供图片中的前提条件,则表示 SELECT * from TableA
WHERE Active =
( CASE @Status WHEN 'N' THEN ('N' AND CONVERT(DATE,ISNULL(DateDeactivated,'01/01/2016'))
BETWEEN CONVERT(DATE,GETDATE()-30) AND CONVERT(DATE,GETDATE())
WHEN 'Y' THEN 'Y' ELSE 'Y' END)
小于getTopdiameter(startPeg)
如果getTopDiamater(endPeg)
至少有一个响铃所以把它写成你需要的条件
endPeg
- 编辑 -
你需要将条件分成不同的if语句(或者还有条件或条件)来处理塔没有钉子的情况 - 当前条件是你的条件,它在第一次移动时失败作为条件{{ 1}}将是假的。如果getRingCount(endPeg) > 0 && getTopdiameter(startPeg) < getTopDiamater(endPeg))
那么您可以直接进行移动而无需检查直径是否兼容。为了便于阅读,我建议你最初将你的条件分开 - 你可以随后根据需要将它们组合起来 - 像这样的伪代码
getRingCount(endPeg) > 0