simulate a combination lock

CONTENTS

  • Simulate a Combination Lock
    • Description
    • Analysis
      • Class Design
        • Class member variables
        • Class member operations
        • Class diagram
      • Flow design
        • A Simple Flowchart
    • Implementation
      • Header File
      • Source File
    • Test
      • Case 1
      • Case 2
      • Case 3
    • Conclusion
    • Reference

Simulate a Combination Lock

Description

Specify, design, and implement a class that can be used in a program that simulates a combination lock. The lock has a circular knob, with the numbers 0 through 39 marked on the edge, and it has a three-number combination, which we’ll call x, y, z. To open the lock, you must turn the knob clockwise at least one entire revolution, stopping with x at the top; then turn the knob counter-clockwise, stopping the second time that y appears at the top; finally turn the knob clockwise again, stopping the next time that z appears at the top. At this point, you may open the lock.
Your lock class should have a constructor that initializes the three-number combination(use 0, 0, 0 for default arguments). Also provide member functions:
( a ) to alter the lock’s combination to a new three-number combination
( b ) to turn the knob in a given direction until a specified number appears at the top
( c ) to close the lock
( d ) to attempt to open the lock
( e ) to inquire about the status of the lock(open or shut)
( f ) to tell you what number is currently at the top

Analysis

This question is located in p120 of Data Structures and Other Objects Using C++(Fourth Edition).
According to the tips from the question, we should design a class to implement a combination lock. To design a class, class member variables and member functions must be taken into consideration.
These questions are not so difficult. I am aimed at practicing my English writing and review the knowledge of software engineering. Pay more effort to the design and documentation instead of codes.

Class Design

Complete a class and draw the class diagram.

Class member variables

To indicate the current value of x, y, z respectively, we declare them as private variables.
To indicate whether the user has turned the knob clockwise one revolution and adjust x, y, z in sequence, we declare a bool variable called has_right_operation_sequence. We need to check it when we attempt to open the clock. To support us in checking the value of has_right_operation_sequence, we declare adjust_one_revolution, adjust_x, adjust_y( both of them are bool variables).
Additionally, we need a integrated value called top to indicate the current value of top. To check whether our tuple is matched with the correct key of the combination lock, we are supposed to declare a structure to hold the key.

Class member operations

I think I need these operation below referenced to a-f:
When it comes to the constructor, we have both a default constructor and a overloaded constructor which receives three integrated values as its arguments. They are:
combination_lock();
combination_lock(int, int, int);
( a )
void turn_knob_clockwise_one_revolution();
int alter_x_to_top();
int alter_y_to_top();
int alter_z_to_top();
( b )
void set_top_val(int val);
If the val is less than 0, it will not pass the assertion. If the val is larger than 39, it will be set to the remaining value after being divided. The actual value called α \alpha α is calculated as below.
α = v a l   m o d   40 \alpha = val\,mod\,40 α=valmod40
( c )
void close_lock();
( d )
int attempt_open_lock();
void initialize_key(int, int, int);
( e )
int lock_status();
( f )
int get_top_val();

Class diagram

This diagram is generated by visual studio 2017.
simulate a combination lock_第1张图片

Flow design

A Simple Flowchart

According to the description of the question, I attempt to draw a flow diagram using UML.

Created with Raphaël 2.2.0 start turn clockwise one revolution set top and adjust x set top and adjust y set top and adjust z confirm? Right sequence? end yes no

Implementation

Header File

// lock.h
#pragma once
struct lock_key {
	int i;
	int j;
	int k;
};

enum lock_status { OPEN, SHUT };

class combination_lock {
public:
	combination_lock() {
		int x = 0;
		int y = 0;
		int z = 0;
		int top = 0;
	};
	combination_lock(int m, int n, int p) {
		int x = m;
		int y = n;
		int z = p;
		int top = 0;
	};
	void turn_knob_clockwise_one_revolution();
	int alter_x_to_top();
	int alter_y_to_top();
	int alter_z_to_top();
	void set_top_val(int);
	void close_lock();
	int attempt_open_lock();
	int lock_status();
	int get_top_val();
	void initialize_key(int, int, int);
private:
	int x, y, z, top;
	bool has_right_operation_sequence = false;
	bool adjust_one_revolution = false;
	bool adjust_x = false;
	bool adjust_y = false;
	int status = SHUT;
	lock_key key;
};

Source File

// lock.cpp
#include "pch.h"
#include "lock.h"
#include 
#include 

void combination_lock::turn_knob_clockwise_one_revolution()
{
	adjust_one_revolution = true;
}

int combination_lock::alter_x_to_top()
{
	assert(adjust_one_revolution);
	adjust_x = true;
	x = top;
	return 0;
}

int combination_lock::alter_y_to_top()
{
	assert(adjust_one_revolution && adjust_x);
	adjust_y = true;
	y = top;
	return 0;
}

int combination_lock::alter_z_to_top()
{
	assert(adjust_one_revolution && adjust_x && adjust_y);
	has_right_operation_sequence = true;
	z = top;
	return 0;
}

void combination_lock::set_top_val(int val)
{
	top = val % 40;
}

void combination_lock::close_lock()
{
	status = SHUT;
}

int combination_lock::attempt_open_lock()
{
	assert(has_right_operation_sequence);
	if ((key.i == x) && (key.j == y) && (key.k == z)) {
		status = OPEN;
		return 0;
	}
	else {
		status = SHUT;
		return -1;
	}
}

int combination_lock::lock_status()
{
	return status;
}

int combination_lock::get_top_val()
{
	return top;
}

void combination_lock::initialize_key(int m, int n, int q)
{
	key.i = m;
	key.j = n;
	key.k = q;
}

Test

Case 1

#include "pch.h"
#include "lock.h"
#include 
/*
 * incorrect combination of x, y, z
 */
int main()
{
	combination_lock a;
	a.initialize_key(1, 2, 3);
	a.turn_knob_clockwise_one_revolution();
	std::cout << "Before operation:\n";
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	a.set_top_val(1);
	a.alter_x_to_top();
	a.set_top_val(2);
	a.alter_y_to_top();
	a.set_top_val(43);
	a.alter_z_to_top();
	std::cout << "After operation:\n";
	if (a.attempt_open_lock() == 0) {
		std::cout << "succeeded to open!\n";
	}
	else {
		std::cout << "failed to open!\n";
	}
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	std::cout << "lock it\n";
	a.close_lock();
	return 0;
}

output(succeed to open):
simulate a combination lock_第2张图片

Case 2

#include "pch.h"
#include "lock.h"
#include 
/*
 * incorrect combination of x, y, z
 */
int main()
{
	combination_lock a;
	a.initialize_key(1, 2, 3);
	a.turn_knob_clockwise_one_revolution();
	std::cout << "Before operation:\n";
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	a.set_top_val(1);
	a.alter_x_to_top();
	a.set_top_val(35);
	a.alter_y_to_top();
	a.set_top_val(43);
	a.alter_z_to_top();
	std::cout << "After operation:\n";
	if (a.attempt_open_lock() == 0) {
		std::cout << "succeeded to open!\n";
	}
	else {
		std::cout << "failed to open!\n";
	}
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	std::cout << "lock it\n";
	a.close_lock();
	return 0;
}

output(incorrect combination):
simulate a combination lock_第3张图片

Case 3

#include "pch.h"
#include "lock.h"
#include 

/* 
 * forget to turn knob clockwise one revolution before operating
 */

int main()
{
	combination_lock a;
	a.initialize_key(1, 2, 3);
	std::cout << "Before operation:\n";
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	a.set_top_val(1);
	a.alter_x_to_top();
	a.set_top_val(2);
	a.alter_y_to_top();
	a.set_top_val(43);
	a.alter_z_to_top();
	std::cout << "After operation:\n";
	if (a.attempt_open_lock() == 0) {
		std::cout << "succeeded to open!\n";
	}
	else {
		std::cout << "failed to open!\n";
	}
	if (a.lock_status() == SHUT) {
		std::cout << "It is locked on!\n";
	}
	else {
		std::cout << "It is unlocked!\n";
	}
	std::cout << "lock it\n";
	a.close_lock();
	return 0;
}

output(wrong operation sequence, an assertion error occurred):
simulate a combination lock_第4张图片

Conclusion

Design is important.

Reference

整理自 Data Structures and Other Objects Using C++ ( Fourth Edition ) Michael Main, Walter Savitch.

你可能感兴趣的:(C++数据结构)